Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes:
  [GFS2] Update git tree name/location
  [DLM] fix iovec length in recvmsg
  [GFS2] Pass the correct value to kunmap_atomic
  [GFS2] Fix bug where lock not held
  [DLM] Kconfig: don't show an empty DLM menu
  [GFS2] Fix uninitialised variable
  [GFS2] Fix a size calculation error
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 692809e..e9762a3 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -12,7 +12,7 @@
 #include <asm/fpu.h>
 #include <asm/machvec.h>
 
-#include <asm/unistd.h>
+#include <linux/syscalls.h>
 
 /* these are C runtime functions with special calling conventions: */
 extern void __divl (void);
diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
index c639d30..8fe7e45 100644
--- a/arch/i386/mach-voyager/voyager_basic.c
+++ b/arch/i386/mach-voyager/voyager_basic.c
@@ -44,7 +44,7 @@
 
 #ifdef CONFIG_SMP
 static void
-voyager_dump(int dummy1, struct pt_regs *dummy2, struct tty_struct *dummy3)
+voyager_dump(int dummy1, struct tty_struct *dummy3)
 {
 	/* get here via a sysrq */
 	voyager_smp_dump();
@@ -166,7 +166,7 @@
  * off the timer tick to the SMP code, since the VIC doesn't have an
  * internal timer (The QIC does, but that's another story). */
 void
-voyager_timer_interrupt(struct pt_regs *regs)
+voyager_timer_interrupt(void)
 {
 	if((jiffies & 0x3ff) == 0) {
 
@@ -202,7 +202,7 @@
 		}
 	}
 #ifdef CONFIG_SMP
-	smp_vic_timer_interrupt(regs);
+	smp_vic_timer_interrupt();
 #endif
 }
 
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index d42422f..f3fea2a 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -85,8 +85,8 @@
 static void ack_special_QIC_CPI(__u8 cpi);
 static void ack_VIC_CPI(__u8 cpi);
 static void send_CPI_allbutself(__u8 cpi);
-static void enable_vic_irq(unsigned int irq);
-static void disable_vic_irq(unsigned int irq);
+static void mask_vic_irq(unsigned int irq);
+static void unmask_vic_irq(unsigned int irq);
 static unsigned int startup_vic_irq(unsigned int irq);
 static void enable_local_vic_irq(unsigned int irq);
 static void disable_local_vic_irq(unsigned int irq);
@@ -205,15 +205,12 @@
 /* The VIC IRQ descriptors -- these look almost identical to the
  * 8259 IRQs except that masks and things must be kept per processor
  */
-static struct hw_interrupt_type vic_irq_type = {
-	.typename = "VIC-level",
-	.startup = startup_vic_irq,
-	.shutdown = disable_vic_irq,
-	.enable = enable_vic_irq,
-	.disable = disable_vic_irq,
-	.ack = before_handle_vic_irq,
-	.end = after_handle_vic_irq,
-	.set_affinity = set_vic_irq_affinity,
+static struct irq_chip vic_chip = {
+	.name		= "VIC",
+	.startup	= startup_vic_irq,
+	.mask		= mask_vic_irq,
+	.unmask		= unmask_vic_irq,
+	.set_affinity	= set_vic_irq_affinity,
 };
 
 /* used to count up as CPUs are brought on line (starts at 0) */
@@ -1144,9 +1141,9 @@
 fastcall void
 smp_qic_timer_interrupt(struct pt_regs *regs)
 {
-	ack_QIC_CPI(QIC_TIMER_CPI);
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	wrapper_smp_local_timer_interrupt(void);
+	ack_QIC_CPI(QIC_TIMER_CPI);
+	wrapper_smp_local_timer_interrupt();
 	set_irq_regs(old_regs);
 }
 
@@ -1270,12 +1267,10 @@
 /* this function is triggered in time.c when a clock tick fires
  * we need to re-broadcast the tick to all CPUs */
 void
-smp_vic_timer_interrupt(struct pt_regs *regs)
+smp_vic_timer_interrupt(void)
 {
-	struct pt_regs *old_regs = set_irq_regs(regs);
 	send_CPI_allbutself(VIC_TIMER_CPI);
 	smp_local_timer_interrupt();
-	set_irq_regs(old_regs);
 }
 
 /* local (per CPU) timer interrupt.  It does both profiling and
@@ -1310,7 +1305,7 @@
 						per_cpu(prof_counter, cpu);
 		}
 
-		update_process_times(user_mode_vm(irq_regs));
+		update_process_times(user_mode_vm(get_irq_regs()));
 	}
 
 	if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
@@ -1397,6 +1392,17 @@
 	return 0;
 }
 
+/* This is a bit of a mess, but forced on us by the genirq changes
+ * there's no genirq handler that really does what voyager wants
+ * so hack it up with the simple IRQ handler */
+static void fastcall
+handle_vic_irq(unsigned int irq, struct irq_desc *desc)
+{
+	before_handle_vic_irq(irq);
+	handle_simple_irq(irq, desc);
+	after_handle_vic_irq(irq);
+}
+
 
 /*  The CPIs are handled in the per cpu 8259s, so they must be
  *  enabled to be received: FIX: enabling the CPIs in the early
@@ -1433,7 +1439,7 @@
 	 * This is for later: first 16 correspond to PC IRQs; next 16
 	 * are Primary MC IRQs and final 16 are Secondary MC IRQs */
 	for(i = 0; i < 48; i++)
-		irq_desc[i].chip = &vic_irq_type;
+		set_irq_chip_and_handler(i, &vic_chip, handle_vic_irq);
 }
 
 /* send a CPI at level cpi to a set of cpus in cpuset (set 1 bit per
@@ -1531,7 +1537,7 @@
 static unsigned int
 startup_vic_irq(unsigned int irq)
 {
-	enable_vic_irq(irq);
+	unmask_vic_irq(irq);
 
 	return 0;
 }
@@ -1558,7 +1564,7 @@
  *    adjust their masks accordingly.  */
 
 static void
-enable_vic_irq(unsigned int irq)
+unmask_vic_irq(unsigned int irq)
 {
 	/* linux doesn't to processor-irq affinity, so enable on
 	 * all CPUs we know about */
@@ -1567,7 +1573,7 @@
 	__u32 processorList = 0;
 	unsigned long flags;
 
-	VDEBUG(("VOYAGER: enable_vic_irq(%d) CPU%d affinity 0x%lx\n",
+	VDEBUG(("VOYAGER: unmask_vic_irq(%d) CPU%d affinity 0x%lx\n",
 		irq, cpu, cpu_irq_affinity[cpu]));
 	spin_lock_irqsave(&vic_irq_lock, flags);
 	for_each_online_cpu(real_cpu) {
@@ -1591,7 +1597,7 @@
 }
 
 static void
-disable_vic_irq(unsigned int irq)
+mask_vic_irq(unsigned int irq)
 {
 	/* lazy disable, do nothing */
 }
@@ -1819,7 +1825,7 @@
 	 * disabled again as it comes in (voyager lazy disable).  If
 	 * the affinity map is tightened to disable the interrupt on a
 	 * cpu, it will be pushed off when it comes in */
-	enable_vic_irq(irq);
+	unmask_vic_irq(irq);
 }
 
 static void
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index f6a0c44..6a461d4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -45,6 +45,9 @@
 config GENERIC_IOMAP
 	bool
 
+config GENERIC_TIME
+	def_bool n
+
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
@@ -357,6 +360,7 @@
 endmenu
 
 menu "Timer support"
+depends on !GENERIC_TIME
 
 config SH_TMU
 	bool "TMU timer support"
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
index 75f91aa..2191791 100644
--- a/arch/sh/boards/hp6xx/hp6xx_apm.c
+++ b/arch/sh/boards/hp6xx/hp6xx_apm.c
@@ -83,7 +83,7 @@
 	return p - buf;
 }
 
-static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev)
 {
 	if (!apm_suspended)
 		apm_queue_event(APM_USER_SUSPEND);
@@ -96,7 +96,7 @@
 	int ret;
 
 	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
-			  SA_INTERRUPT, MODNAME, 0);
+			  IRQF_DISABLED, MODNAME, 0);
 	if (unlikely(ret < 0)) {
 		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 		       HP680_BTN_IRQ);
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
index 0b7bee1..e625249 100644
--- a/arch/sh/boards/landisk/landisk_pwb.c
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -135,7 +135,7 @@
 	return count;
 }
 
-static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sw_interrupt(int irq, void *dev_id)
 {
 	landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
 	disable_irq(IRQ_BUTTON);
diff --git a/arch/sh/boards/mpc1211/setup.c b/arch/sh/boards/mpc1211/setup.c
index 01c10fa..7c3d1d3 100644
--- a/arch/sh/boards/mpc1211/setup.c
+++ b/arch/sh/boards/mpc1211/setup.c
@@ -69,7 +69,6 @@
 
 static unsigned char m_irq_mask = 0xfb;
 static unsigned char s_irq_mask = 0xff;
-volatile unsigned long irq_err_count;
 
 static void disable_mpc1211_irq(unsigned int irq)
 {
@@ -118,7 +117,7 @@
 	if(irq < 8) {
 		if(m_irq_mask & (1<<irq)){
 		  if(!mpc1211_irq_real(irq)){
-		    irq_err_count++;
+		    atomic_inc(&irq_err_count)
 		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
 		   }
 		} else {
@@ -131,7 +130,7 @@
 	} else {
 		if(s_irq_mask & (1<<(irq - 8))){
 		  if(!mpc1211_irq_real(irq)){
-		    irq_err_count++;
+		    atomic_inc(&irq_err_count);
 		    printk("spurious 8259A interrupt: IRQ %x\n",irq);
 		  }
 		} else {
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
index 2d960e9..b544772 100644
--- a/arch/sh/boards/renesas/r7780rp/irq.c
+++ b/arch/sh/boards/renesas/r7780rp/irq.c
@@ -1,18 +1,16 @@
 /*
- * linux/arch/sh/boards/renesas/r7780rp/irq.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
  * Renesas Solutions Highlander R7780RP-1 Support.
  *
- * Modified for R7780RP-1 by
- * Atom Create Engineering Co., Ltd. 2002.
+ * Copyright (C) 2002  Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/r7780rp/r7780rp.h>
 
 #ifdef CONFIG_SH_R7780MP
 static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
@@ -20,71 +18,26 @@
 static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
 #endif
 
-static void enable_r7780rp_irq(unsigned int irq);
-static void disable_r7780rp_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_r7780rp_irq disable_r7780rp_irq
-
-static void ack_r7780rp_irq(unsigned int irq);
-static void end_r7780rp_irq(unsigned int irq);
-
-static unsigned int startup_r7780rp_irq(unsigned int irq)
+static void enable_r7780rp_irq(unsigned int irq)
 {
-	enable_r7780rp_irq(irq);
-	return 0; /* never anything pending */
+	/* Set priority in IPR back to original value */
+	ctrl_outw(ctrl_inw(IRLCNTR1) | (1 << mask_pos[irq]), IRLCNTR1);
 }
 
 static void disable_r7780rp_irq(unsigned int irq)
 {
-	unsigned short val;
-	unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
-
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(IRLCNTR1);
-	val &= mask;
-	ctrl_outw(val, IRLCNTR1);
+	ctrl_outw(ctrl_inw(IRLCNTR1) & (0xffff ^ (1 << mask_pos[irq])),
+		  IRLCNTR1);
 }
 
-static void enable_r7780rp_irq(unsigned int irq)
-{
-	unsigned short val;
-	unsigned short value = (0x0001 << mask_pos[irq]);
-
-	/* Set priority in IPR back to original value */
-	val = ctrl_inw(IRLCNTR1);
-	val |= value;
-	ctrl_outw(val, IRLCNTR1);
-}
-
-static void ack_r7780rp_irq(unsigned int irq)
-{
-	disable_r7780rp_irq(irq);
-}
-
-static void end_r7780rp_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_r7780rp_irq(irq);
-}
-
-static struct hw_interrupt_type r7780rp_irq_type = {
-	.typename = "R7780RP-IRQ",
-	.startup = startup_r7780rp_irq,
-	.shutdown = shutdown_r7780rp_irq,
-	.enable = enable_r7780rp_irq,
-	.disable = disable_r7780rp_irq,
-	.ack = ack_r7780rp_irq,
-	.end = end_r7780rp_irq,
+static struct irq_chip r7780rp_irq_chip __read_mostly = {
+	.name		= "r7780rp",
+	.mask		= disable_r7780rp_irq,
+	.unmask		= enable_r7780rp_irq,
+	.mask_ack	= disable_r7780rp_irq,
 };
 
-static void make_r7780rp_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	irq_desc[irq].chip = &r7780rp_irq_type;
-	disable_r7780rp_irq(irq);
-}
-
 /*
  * Initialize IRQ setting
  */
@@ -92,24 +45,10 @@
 {
 	int i;
 
-	/* IRL0=PCI Slot #A
-	 * IRL1=PCI Slot #B
-	 * IRL2=PCI Slot #C
-	 * IRL3=PCI Slot #D
-	 * IRL4=CF Card
-	 * IRL5=CF Card Insert
-	 * IRL6=M66596
-	 * IRL7=SD Card
-	 * IRL8=Touch Panel
-	 * IRL9=SCI
-	 * IRL10=Serial
-	 * IRL11=Extention #A
-	 * IRL11=Extention #B
-	 * IRL12=Debug LAN
-	 * IRL13=Push Switch
-	 * IRL14=ZiggBee IO
-	 */
-
-	for (i=0; i<15; i++)
-		make_r7780rp_irq(i);
+	for (i = 0; i < 15; i++) {
+		disable_irq_nosync(i);
+		set_irq_chip_and_handler(i, &r7780rp_irq_chip,
+					 handle_level_irq);
+		enable_r7780rp_irq(i);
+	}
 }
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index f5e98c5..540d0bf 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -33,7 +33,7 @@
  * EraseConfig handling functions
  */
 
-static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id)
 {
 	volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000;
 
diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c
index 38f1e81..4d49b5c 100644
--- a/arch/sh/cchips/hd6446x/hd64461/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64461/setup.c
@@ -71,7 +71,7 @@
 	.end		= end_hd64461_irq,
 };
 
-static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hd64461_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c
index 72320d0..4343185 100644
--- a/arch/sh/cchips/hd6446x/hd64465/gpio.c
+++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c
@@ -85,7 +85,7 @@
     void *dev;
 } handlers[GPIO_NPORTS * 8];
 
-static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hd64465_gpio_interrupt(int irq, void *dev)
 {
     	unsigned short port, pin, isr, mask, portpin;
 	
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
index 30573d3..d126e1f 100644
--- a/arch/sh/cchips/hd6446x/hd64465/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -84,7 +84,7 @@
 };
 
 
-static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t hd64465_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 392c8b1..bf1b28f 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -88,8 +88,7 @@
 	.end = end_voyagergx_irq,
 };
 
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
-				      struct pt_regs *regs)
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id)
 {
 	printk(KERN_INFO
 	       "VoyagerGX: spurious interrupt, status: 0x%x\n",
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index 9cb0709..0caf11b 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -51,7 +51,7 @@
 	((g2_dma->channel[i].size - \
 	  g2_dma->status[i].size) & 0x0fffffff)
 
-static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t g2_dma_interrupt(int irq, void *dev_id)
 {
 	int i;
 
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index c1b6bc2..838fad5 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -21,7 +21,7 @@
 static unsigned int xfer_complete;
 static int count;
 
-static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id)
 {
 	if (get_dma_residue(PVR2_CASCADE_CHAN)) {
 		printk(KERN_WARNING "DMA: SH DMAC did not complete transfer "
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index cbbe8bc..d8ece20 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -60,9 +60,9 @@
  * Besides that it needs to waken any waiting process, which should handle
  * setting up the next transfer.
  */
-static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_tei(int irq, void *dev_id)
 {
-	struct dma_channel *chan = (struct dma_channel *)dev_id;
+	struct dma_channel *chan = dev_id;
 	u32 chcr;
 
 	chcr = ctrl_inl(CHCR[chan->chan]);
@@ -228,7 +228,7 @@
 }
 
 #if defined(CONFIG_CPU_SH4)
-static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_err(int irq, void *dummy)
 {
 	dmaor_reset();
 	disable_irq(irq);
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index dbe8378..85e1ee2 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -155,7 +155,7 @@
 	 */
 	pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
 		 PCIBIOS_MIN_IO, (64 << 10),
-		 SH4_PCI_IO_BASE + PCIBIOS_MIN_IO);
+		 SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO);
 
 	/*
 	 * XXX: For now, leave this board-specific. In the event we have other
@@ -163,7 +163,7 @@
 	 */
 #ifdef CONFIG_SH_BIGSUR
 	bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
-			SH4_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
+			SH7751_PCI_IO_BASE + PCIBIOS_MIN_IO, 0);
 #endif
 
 	/* Make sure the MSB's of IO window are set to access PCI space
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 4ab5ea6..efecb3d 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -161,7 +161,7 @@
 	"Memory Write-and-Invalidate"
 };
 
-static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t st40_pci_irq(int irq, void *dev_instance)
 {
 	unsigned pci_int, pci_air, pci_cir, pci_aint;
 	static int count=0;
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index e30e4b7..d4b2bb7 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -10,93 +10,32 @@
  * These are the "new Hitachi style" interrupts, as present on the
  * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/machvec.h>
-
-struct intc2_data {
-	unsigned char msk_offset;
-	unsigned char msk_shift;
-
-	int (*clear_irq) (int);
-};
-
-static struct intc2_data intc2_data[NR_INTC2_IRQS];
-
-static void enable_intc2_irq(unsigned int irq);
-static void disable_intc2_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_intc2_irq disable_intc2_irq
-
-static void mask_and_ack_intc2(unsigned int);
-static void end_intc2_irq(unsigned int irq);
-
-static unsigned int startup_intc2_irq(unsigned int irq)
-{
-	enable_intc2_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type intc2_irq_type = {
-	.typename	= "INTC2-IRQ",
-	.startup	= startup_intc2_irq,
-	.shutdown	= shutdown_intc2_irq,
-	.enable		= enable_intc2_irq,
-	.disable	= disable_intc2_irq,
-	.ack		= mask_and_ack_intc2,
-	.end		= end_intc2_irq
-};
 
 static void disable_intc2_irq(unsigned int irq)
 {
-	int irq_offset = irq - INTC2_FIRST_IRQ;
-	int msk_shift, msk_offset;
-
-	/* Sanity check */
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	msk_shift = intc2_data[irq_offset].msk_shift;
-	msk_offset = intc2_data[irq_offset].msk_offset;
-
-	ctrl_outl(1 << msk_shift,
-		  INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset);
+	struct intc2_data *p = get_irq_chip_data(irq);
+	ctrl_outl(1 << p->msk_shift,
+		  INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
 }
 
 static void enable_intc2_irq(unsigned int irq)
 {
-	int irq_offset = irq - INTC2_FIRST_IRQ;
-	int msk_shift, msk_offset;
-
-	/* Sanity check */
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	msk_shift = intc2_data[irq_offset].msk_shift;
-	msk_offset = intc2_data[irq_offset].msk_offset;
-
-	ctrl_outl(1 << msk_shift,
-		  INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset);
+	struct intc2_data *p = get_irq_chip_data(irq);
+	ctrl_outl(1 << p->msk_shift,
+		  INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
 }
 
-static void mask_and_ack_intc2(unsigned int irq)
-{
-	disable_intc2_irq(irq);
-}
-
-static void end_intc2_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_intc2_irq(irq);
-
-	if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq))
-		intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq);
-}
+static struct irq_chip intc2_irq_chip = {
+	.typename	= "intc2",
+	.mask		= disable_intc2_irq,
+	.unmask		= enable_intc2_irq,
+	.mask_ack	= disable_intc2_irq,
+};
 
 /*
  * Setup an INTC2 style interrupt.
@@ -108,46 +47,30 @@
  *                         |     |             |  |
  *    make_intc2_irq(84,   0,   16,            0, 13);
  */
-void make_intc2_irq(unsigned int irq,
-		    unsigned int ipr_offset, unsigned int ipr_shift,
-		    unsigned int msk_offset, unsigned int msk_shift,
-		    unsigned int priority)
+void make_intc2_irq(struct intc2_data *p)
 {
-	int irq_offset = irq - INTC2_FIRST_IRQ;
 	unsigned int flags;
 	unsigned long ipr;
 
-	if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
-		return;
-
-	disable_irq_nosync(irq);
-
-	/* Fill the data we need */
-	intc2_data[irq_offset].msk_offset = msk_offset;
-	intc2_data[irq_offset].msk_shift  = msk_shift;
-	intc2_data[irq_offset].clear_irq = NULL;
+	disable_irq_nosync(p->irq);
 
 	/* Set the priority level */
 	local_irq_save(flags);
 
-	ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
-	ipr &= ~(0xf << ipr_shift);
-	ipr |= priority << ipr_shift;
-	ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
+	ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
+	ipr &= ~(0xf << p->ipr_shift);
+	ipr |= p->priority << p->ipr_shift;
+	ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
 
 	local_irq_restore(flags);
 
-	irq_desc[irq].chip = &intc2_irq_type;
+	set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq);
+	set_irq_chip_data(p->irq, p);
 
-	disable_intc2_irq(irq);
+	enable_intc2_irq(p->irq);
 }
 
-static struct intc2_init {
-	unsigned short irq;
-	unsigned char ipr_offset, ipr_shift;
-	unsigned char msk_offset, msk_shift;
-	unsigned char priority;
-} intc2_init_data[]  __initdata = {
+static struct intc2_data intc2_irq_table[] = {
 #if defined(CONFIG_CPU_SUBTYPE_ST40)
 	{64,  0,  0, 0,  0, 13},	/* PCI serr */
 	{65,  0,  4, 0,  1, 13},	/* PCI err */
@@ -266,19 +189,6 @@
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) {
-		struct intc2_init *p = intc2_init_data + i;
-		make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
-			       p-> msk_offset, p->msk_shift, p->priority);
-	}
+	for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++)
+		make_intc2_irq(intc2_irq_table + i);
 }
-
-/* Adds a termination callback to the interrupt */
-void intc2_add_clear_irq(int irq, int (*fn)(int))
-{
-	if (unlikely(irq < INTC2_FIRST_IRQ))
-		return;
-
-	intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
-}
-
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index f785822..8944abd 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -1,11 +1,10 @@
 /*
- * arch/sh/kernel/cpu/irq/ipr.c
+ * Interrupt handling for IPR-based IRQ.
  *
  * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
  * Copyright (C) 2000  Kazumoto Kojima
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- *
- * Interrupt handling for IPR-based IRQ.
+ * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 2006  Paul Mundt
  *
  * Supported system:
  *	On-chip supporting modules (TMU, RTC, etc.).
@@ -13,12 +12,13 @@
  *	Hitachi SolutionEngine external I/O:
  *		MS7709SE01, MS7709ASE01, and MS7750SE01
  *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/module.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
@@ -28,93 +28,45 @@
 	int shift;		/* Shifts of the 16-bit data */
 	int priority;		/* The priority */
 };
-static struct ipr_data ipr_data[NR_IRQS];
-
-static void enable_ipr_irq(unsigned int irq);
-static void disable_ipr_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_ipr_irq disable_ipr_irq
-
-static void mask_and_ack_ipr(unsigned int);
-static void end_ipr_irq(unsigned int irq);
-
-static unsigned int startup_ipr_irq(unsigned int irq)
-{
-	enable_ipr_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type ipr_irq_type = {
-	.typename = "IPR-IRQ",
-	.startup = startup_ipr_irq,
-	.shutdown = shutdown_ipr_irq,
-	.enable = enable_ipr_irq,
-	.disable = disable_ipr_irq,
-	.ack = mask_and_ack_ipr,
-	.end = end_ipr_irq
-};
 
 static void disable_ipr_irq(unsigned int irq)
 {
-	unsigned long val;
-	unsigned int addr = ipr_data[irq].addr;
-	unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
-
+	struct ipr_data *p = get_irq_chip_data(irq);
 	/* Set the priority in IPR to 0 */
-	val = ctrl_inw(addr);
-	val &= mask;
-	ctrl_outw(val, addr);
+	ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
-	unsigned long val;
-	unsigned int addr = ipr_data[irq].addr;
-	int priority = ipr_data[irq].priority;
-	unsigned short value = (priority << ipr_data[irq].shift);
-
+	struct ipr_data *p = get_irq_chip_data(irq);
 	/* Set priority in IPR back to original value */
-	val = ctrl_inw(addr);
-	val |= value;
-	ctrl_outw(val, addr);
+	ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
 }
 
-static void mask_and_ack_ipr(unsigned int irq)
-{
-	disable_ipr_irq(irq);
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
-	/* This is needed when we use edge triggered setting */
-	/* XXX: Is it really needed? */
-	if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
-		/* Clear external interrupt request */
-		int a = ctrl_inb(INTC_IRR0);
-		a &= ~(1 << (irq - IRQ0_IRQ));
-		ctrl_outb(a, INTC_IRR0);
-	}
-#endif
-}
-
-static void end_ipr_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ipr_irq(irq);
-}
+static struct irq_chip ipr_irq_chip = {
+	.name		= "ipr",
+	.mask		= disable_ipr_irq,
+	.unmask		= enable_ipr_irq,
+	.mask_ack	= disable_ipr_irq,
+};
 
 void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
 {
-	disable_irq_nosync(irq);
-	ipr_data[irq].addr = addr;
-	ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
-	ipr_data[irq].priority = priority;
+	struct ipr_data ipr_data;
 
-	irq_desc[irq].chip = &ipr_irq_type;
-	disable_ipr_irq(irq);
+	disable_irq_nosync(irq);
+
+	ipr_data.addr = addr;
+	ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */
+	ipr_data.priority = priority;
+
+	set_irq_chip_and_handler(irq, &ipr_irq_chip, handle_level_irq);
+	set_irq_chip_data(irq, &ipr_data);
+
+	enable_ipr_irq(irq);
 }
 
+/* XXX: This needs to die a horrible death.. */
 void __init init_IRQ(void)
 {
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 44daf44..6be46f0 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -49,198 +49,3 @@
 #endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap	/* 1E0 */
-ENTRY(interrupt_table)
-	! external hardware
-	.long	do_IRQ	! 0000		/* 200 */
-	.long	do_IRQ	! 0001
-	.long	do_IRQ	! 0010
-	.long	do_IRQ	! 0011
-	.long	do_IRQ	! 0100
-	.long	do_IRQ	! 0101
-	.long	do_IRQ	! 0110
-	.long	do_IRQ	! 0111
-	.long	do_IRQ	! 1000		/* 300 */
-	.long	do_IRQ	! 1001
-	.long	do_IRQ	! 1010
-	.long	do_IRQ	! 1011
-	.long	do_IRQ	! 1100
-	.long	do_IRQ	! 1101
-	.long	do_IRQ	! 1110
-	.long	exception_error		
-	! Internal hardware
-	.long	do_IRQ	! TMU0 tuni0	/* 400 */
-	.long	do_IRQ	! TMU1 tuni1
-	.long	do_IRQ	! TMU2 tuni2
-	.long	do_IRQ	!      ticpi2
-	.long	do_IRQ	! RTC  ati
-	.long	do_IRQ	!      pri
-	.long	do_IRQ	!      cui
-	.long	do_IRQ	! SCI  eri
-	.long	do_IRQ	!      rxi	/* 500 */
-	.long	do_IRQ	!      txi
-	.long	do_IRQ	!      tei
-	.long	do_IRQ	! WDT  iti	/* 560 */
-	.long	do_IRQ	! REF  rcmi
-	.long	do_IRQ	!      rovi
-	.long	do_IRQ			
-	.long	do_IRQ			/* 5E0 */
-#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7710)
-	.long	do_IRQ	! 32 IRQ  irq0	/* 600 */
-	.long	do_IRQ	! 33      irq1
-	.long	do_IRQ	! 34      irq2
-	.long	do_IRQ	! 35      irq3
-	.long	do_IRQ	! 36      irq4
-	.long	do_IRQ	! 37      irq5
-	.long	do_IRQ	! 38
-	.long	do_IRQ	! 39
-	.long	do_IRQ	! 40 PINT pint0-7	/* 700 */
-	.long	do_IRQ	! 41      pint8-15
-	.long	do_IRQ	! 42
-	.long	do_IRQ	! 43
-	.long	do_IRQ	! 44
-	.long	do_IRQ	! 45	
-	.long	do_IRQ	! 46
-	.long	do_IRQ	! 47
-	.long	do_IRQ	! 48 DMAC dei0	/* 800 */
-	.long	do_IRQ	! 49      dei1
-	.long	do_IRQ	! 50      dei2
-	.long	do_IRQ	! 51      dei3
-	.long	do_IRQ	! 52 IrDA eri1
-	.long	do_IRQ	! 53      rxi1
-	.long	do_IRQ	! 54      bri1
-	.long	do_IRQ	! 55      txi1
-	.long	do_IRQ	! 56 SCIF eri2
-	.long	do_IRQ	! 57      rxi2
-	.long	do_IRQ	! 58      bri2
-	.long	do_IRQ	! 59      txi2
-	.long	do_IRQ	! 60 ADC  adi	/* 980 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
-	.long	exception_none	! 61	/* 9A0 */
-	.long	exception_none	! 62
-	.long	exception_none	! 63
-	.long	exception_none	! 64	/* A00 */
-	.long	do_IRQ	! 65 USB  usi0
-	.long	do_IRQ	! 66      usi1
-	.long	exception_none	! 67
-	.long	exception_none	! 68
-	.long	exception_none	! 69
-	.long	exception_none	! 70
-	.long	exception_none	! 71
-	.long	exception_none	! 72	/* B00 */
-	.long	exception_none	! 73
-	.long	exception_none	! 74
-	.long	exception_none	! 75
-	.long	exception_none	! 76
-	.long	exception_none	! 77
-	.long	exception_none	! 78
-	.long	exception_none	! 79
-	.long	do_IRQ	! 80 TPU0 tpi0	/* C00 */
-	.long	do_IRQ	! 81 TPU1 tpi1
-	.long	exception_none	! 82
-	.long	exception_none	! 83
-	.long	do_IRQ	! 84 TPU2 tpi2
-	.long	do_IRQ	! 85 TPU3 tpi3	/* CA0 */
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7300)
-	.long   do_IRQ	! 61 LCDC lcdi	/* 9A0 */
-	.long   do_IRQ	! 62 PCC  pcc0i
-	.long   do_IRQ	! 63      pcc1i	/* 9E0 */
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7710)
-	.long   exception_none	! 61 	/* 9A0 */
-	.long   exception_none	! 62
-	.long   exception_none	! 63
-	.long   exception_none	! 64	/* A00 */
-	.long   exception_none	! 65
-	.long   exception_none	! 66
-	.long   exception_none	! 67
-	.long   exception_none	! 68
-	.long   exception_none	! 69
-	.long   exception_none	! 70
-	.long   exception_none	! 71
-	.long   exception_none	! 72	/* B00 */
-	.long   exception_none	! 73
-	.long   exception_none	! 74
-	.long   exception_none	! 75
-	.long   do_IRQ	! 76 DMAC2 dei4	/* B80 */
-	.long   do_IRQ	! 77 DMAC2 dei5
-	.long   exception_none	! 78
-	.long   do_IRQ	! 79 IPSEC ipseci /* BE0 */
-	.long   do_IRQ	! 80 EDMAC eint0 /* C00 */
-	.long   do_IRQ	! 81 EDMAC eint1
-	.long   do_IRQ	! 82 EDMAC eint2
-	.long   exception_none	! 83	/* C60 */
-	.long   exception_none	! 84
-	.long   exception_none	! 85
-	.long   exception_none	! 86
-	.long   exception_none	! 87
-	.long   exception_none	! 88	/* D00 */
-	.long   exception_none	! 89
-	.long   exception_none	! 90
-	.long   exception_none	! 91
-	.long   exception_none	! 92
-	.long   exception_none	! 93
-	.long   exception_none	! 94
-	.long   exception_none	! 95
-	.long   do_IRQ	! 96 SIOF eri0	/* E00 */
-	.long   do_IRQ	! 97      txi0
-	.long   do_IRQ	! 98      rxi0
-	.long   do_IRQ	! 99      cci0
-	.long   do_IRQ	! 100     eri1	/* E80 */
-	.long   do_IRQ	! 101     txi1
-	.long   do_IRQ	! 102     rxi2
-	.long   do_IRQ	! 103     cci3
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-	.long   do_IRQ	! 64
-	.long   do_IRQ	! 65
-	.long   do_IRQ	! 66
-	.long   do_IRQ	! 67
-	.long   do_IRQ	! 68
-	.long   do_IRQ	! 69
-	.long   do_IRQ	! 70
-	.long   do_IRQ	! 71
-	.long   do_IRQ	! 72
-	.long   do_IRQ	! 73
-	.long   do_IRQ	! 74
-	.long   do_IRQ	! 75
-	.long   do_IRQ	! 76
-	.long   do_IRQ	! 77
-	.long   do_IRQ	! 78
-	.long   do_IRQ	! 79
-	.long   do_IRQ	! 80 SCIF0(SH7300)
-	.long   do_IRQ	! 81
-	.long   do_IRQ	! 82
-	.long   do_IRQ	! 83
-	.long   do_IRQ	! 84
-	.long   do_IRQ	! 85
-	.long   do_IRQ	! 86
-	.long   do_IRQ	! 87
-	.long   do_IRQ	! 88
-	.long   do_IRQ	! 89
-	.long   do_IRQ	! 90
-	.long   do_IRQ	! 91
-	.long   do_IRQ	! 92
-	.long   do_IRQ	! 93
-	.long   do_IRQ	! 94
-	.long   do_IRQ	! 95
-	.long   do_IRQ	! 96
-	.long   do_IRQ	! 97
-	.long   do_IRQ	! 98
-	.long   do_IRQ	! 99
-	.long   do_IRQ	! 100
-	.long   do_IRQ	! 101
-	.long   do_IRQ	! 102
-	.long   do_IRQ	! 103
-	.long   do_IRQ	! 104
-	.long   do_IRQ	! 105
-	.long   do_IRQ	! 106
-	.long   do_IRQ	! 107
-	.long   do_IRQ	! 108
-#endif
-#endif
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
index 7146893..3f4cd04 100644
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ b/arch/sh/kernel/cpu/sh4/ex.S
@@ -53,503 +53,3 @@
 #endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap	/* 1E0 */
-ENTRY(interrupt_table)
-	! external hardware
-	.long	do_IRQ	! 0000		/* 200 */
-	.long	do_IRQ	! 0001
-	.long	do_IRQ	! 0010
-	.long	do_IRQ	! 0011
-	.long	do_IRQ	! 0100
-	.long	do_IRQ	! 0101
-	.long	do_IRQ	! 0110
-	.long	do_IRQ	! 0111
-	.long	do_IRQ	! 1000		/* 300 */
-	.long	do_IRQ	! 1001
-	.long	do_IRQ	! 1010
-	.long	do_IRQ	! 1011
-	.long	do_IRQ	! 1100
-	.long	do_IRQ	! 1101
-	.long	do_IRQ	! 1110
-	.long	exception_error		
-	! Internal hardware
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
-	.long	do_IRQ	! TMU0 tuni0	/* 400 */
-	.long	do_IRQ	! TMU1 tuni1
-	.long	do_IRQ	! TMU2 tuni2
-	.long	do_IRQ	!      ticpi2
-#if  defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* 500 */
-	.long	exception_error
-	.long	exception_error
-#else
-	.long	do_IRQ	! RTC  ati
-	.long	do_IRQ	!      pri
-	.long	do_IRQ	!      cui
-	.long	do_IRQ	! SCI  eri
-	.long	do_IRQ	!      rxi	/* 500 */
-	.long	do_IRQ	!      txi
-	.long	do_IRQ	!      tei
-#endif
-	.long	do_IRQ	! WDT  iti	/* 560 */
-	.long	do_IRQ	! REF  rcmi
-	.long	do_IRQ	!      rovi
-	.long	do_IRQ			
-	.long	do_IRQ			/* 5E0 */
-	.long	do_IRQ	! 32 Hitachi UDI	/* 600 */
-	.long	do_IRQ	! 33 GPIO
-	.long	do_IRQ	! 34 DMAC dmte0
-	.long	do_IRQ	! 35      dmte1
-	.long	do_IRQ	! 36      dmte2
-	.long	do_IRQ	! 37      dmte3
-	.long	do_IRQ	! 38      dmae
-	.long	exception_error			! 39	/* 6E0 */
-#if defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	exception_error				/* 700 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error				/* 760 */
-#else
-	.long	do_IRQ	! 40 SCIF eri		/* 700 */
-	.long	do_IRQ	! 41      rxi
-	.long	do_IRQ	! 42      bri
-	.long	do_IRQ	! 43      txi
-#endif
-#if CONFIG_NR_ONCHIP_DMA_CHANNELS == 8
-	.long	do_IRQ	! 44 DMAC dmte4		/* 780 */
-	.long	do_IRQ	! 45      dmte5
-	.long	do_IRQ	! 46      dmte6
-	.long	do_IRQ	! 47      dmte7		/* 7E0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-	.long	do_IRQ	! 44 IIC1 ali		/* 780 */
-	.long	do_IRQ	! 45      tacki
-	.long	do_IRQ	! 46      waiti
-	.long	do_IRQ	! 47      dtei		/* 7E0 */
-	.long	do_IRQ	! 48 DMAC dei0		/* 800 */
-	.long	do_IRQ	! 49      dei1		/* 820 */
-#else
-	.long	exception_error			! 44	/* 780 */
-	.long	exception_error			! 45
-	.long	exception_error			! 46
-	.long	exception_error			! 47
-#endif
-#if defined(CONFIG_SH_FPU)
-	.long	do_fpu_state_restore	! 48	/* 800 */
-	.long	do_fpu_state_restore	! 49	/* 820 */
-#elif !defined(CONFIG_CPU_SUBTYPE_SH7343) && \
-      !defined(CONFIG_CPU_SUBTYPE_SH73180)
-	.long	exception_error
-	.long	exception_error
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7751)
-	.long	exception_error			/* 840 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* 900 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! PCI serr	/* A00 */
-	.long	do_IRQ	!     dma3
-	.long	do_IRQ	!     dma2
-	.long	do_IRQ	!     dma1
-	.long	do_IRQ	!     dma0
-	.long	do_IRQ	!     pwon
-	.long	do_IRQ	!     pwdwn
-	.long	do_IRQ	!     err
-	.long	do_IRQ	! TMU3 tuni3	/* B00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! TMU4 tuni4	/* B80 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-	.long	do_IRQ	! IRQ	irq6	/* 840 */
-	.long	do_IRQ	!	irq7
-	.long	do_IRQ	! SCIF	eri0
-	.long	do_IRQ	!	rxi0
-	.long	do_IRQ	!	bri0
-	.long	do_IRQ	!	txi0
-	.long	do_IRQ	! HCAN2	cani0	/* 900 */
-	.long	do_IRQ	!	cani1
-	.long	do_IRQ	! SSI	ssii0
-	.long	do_IRQ	!	ssii1
-	.long	do_IRQ	! HAC	haci0
-	.long	do_IRQ	!	haci1
-	.long	do_IRQ	! IIC	iici0
-	.long	do_IRQ	!	iici1
-	.long	do_IRQ	! USB	usbi	/* A00 */
-	.long	do_IRQ	! LCDC	vint
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! DMABRG dmabrgi0
-	.long	do_IRQ	!        dmabrgi1
-	.long	do_IRQ	!        dmabrgi2
-	.long	exception_error
-	.long	do_IRQ	! SCIF	eri1	/* B00 */
-	.long	do_IRQ	!	rxi1
-	.long	do_IRQ	!	bri1
-	.long	do_IRQ	!	txi1
-	.long	do_IRQ	!	eri2
-	.long	do_IRQ	!	rxi2
-	.long	do_IRQ	!	bri2
-	.long	do_IRQ  !	txi2
-	.long	do_IRQ	! SIM	simeri	/* C00 */
-	.long	do_IRQ	!	simrxi
-	.long	do_IRQ	!	simtxi
-	.long	do_IRQ	!	simtei
-	.long	do_IRQ	! HSPI	spii
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MMCIF	mmci0	/* D00 */
-	.long	do_IRQ	!	mmci1
-	.long	do_IRQ	!	mmci2
-	.long	do_IRQ	!	mmci3
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* E00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MFI	mfii
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error			/* F00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! ADC	adi
-	.long	do_IRQ	! CMT	cmti	/* FA0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7343)
-	.long	do_IRQ	!  50 0x840
-	.long	do_IRQ	!  51 0x860
-	.long	do_IRQ	!  52 0x880
-	.long	do_IRQ	!  53 0x8a0
-	.long	do_IRQ	!  54 0x8c0
-	.long	do_IRQ	!  55 0x8e0
-	.long	do_IRQ	!  56 0x900
-	.long	do_IRQ	!  57 0x920
-	.long	do_IRQ	!  58 0x940
-	.long	do_IRQ	!  59 0x960
-	.long	do_IRQ	!  60 0x980
-	.long	do_IRQ	!  61 0x9a0
-	.long	do_IRQ	!  62 0x9c0
-	.long	do_IRQ	!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00
-	.long	do_IRQ	!  65 0xa20
-	.long	do_IRQ	!  66 0xa40
-	.long	do_IRQ	!  67 0xa60
-	.long	do_IRQ	!  68 0xa80
-	.long	do_IRQ	!  69 0xaa0
-	.long	do_IRQ	!  70 0xac0
-	.long	do_IRQ	!  71 0xae0
-	.long	do_IRQ	!  72 0xb00
-	.long	do_IRQ	!  73 0xb20
-	.long	do_IRQ	!  74 0xb40
-	.long	do_IRQ	!  75 0xb60
-	.long	do_IRQ	!  76 0xb80
-	.long	do_IRQ	!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0
-	.long	do_IRQ	!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00
-	.long	do_IRQ	!  81 0xc20
-	.long	do_IRQ	!  82 0xc40
-	.long	do_IRQ	!  83 0xc60
-	.long	do_IRQ	!  84 0xc80
-	.long	do_IRQ	!  85 0xca0
-	.long	do_IRQ	!  86 0xcc0
-	.long	do_IRQ	!  87 0xce0
-	.long	do_IRQ	!  88 0xd00
-	.long	do_IRQ	!  89 0xd20
-	.long	do_IRQ	!  90 0xd40
-	.long	do_IRQ	!  91 0xd60
-	.long	do_IRQ	!  92 0xd80
-	.long	do_IRQ	!  93 0xda0
-	.long	do_IRQ	!  94 0xdc0
-	.long	do_IRQ	!  95 0xde0
-	.long	do_IRQ	!  96 0xe00
-	.long	do_IRQ	!  97 0xe20
-	.long	do_IRQ	!  98 0xe40
-	.long	do_IRQ	!  99 0xe60
-	.long	do_IRQ	! 100 0xe80
-	.long	do_IRQ	! 101 0xea0
-	.long	do_IRQ	! 102 0xec0
-	.long	do_IRQ	! 103 0xee0
-	.long	do_IRQ	! 104 0xf00
-	.long	do_IRQ	! 105 0xf20
-	.long	do_IRQ	! 106 0xf40
-	.long	do_IRQ	! 107 0xf60
-	.long	do_IRQ	! 108 0xf80
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-	.long	exception_error			!  50 0x840
-	.long	exception_error			!  51 0x860
-	.long	exception_error			!  52 0x880
-	.long	exception_error			!  53 0x8a0
-	.long	exception_error			!  54 0x8c0
-	.long	exception_error			!  55 0x8e0
-	.long	exception_error			!  56 0x900
-	.long	exception_error			!  57 0x920
-	.long	exception_error			!  58 0x940
-	.long	exception_error			!  59 0x960
-	.long	exception_error			!  60 0x980
-	.long	exception_error			!  61 0x9a0
-	.long	exception_error			!  62 0x9c0
-	.long	exception_error			!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00 PCI serr
-	.long	do_IRQ	!  65 0xa20     err
-	.long	do_IRQ	!  66 0xa40     ad
-	.long	do_IRQ	!  67 0xa60     pwr_dwn
-	.long	exception_error			!  68 0xa80
-	.long	exception_error			!  69 0xaa0
-	.long	exception_error			!  70 0xac0
-	.long	exception_error			!  71 0xae0
-	.long	do_IRQ	!  72 0xb00 DMA INT0
-	.long	do_IRQ	!  73 0xb20     INT1
-	.long	do_IRQ	!  74 0xb40     INT2
-	.long	do_IRQ	!  75 0xb60     INT3
-	.long	do_IRQ	!  76 0xb80     INT4
-	.long	exception_error			!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0 DMA ERR
-	.long	exception_error			!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00 PIO0
-	.long	do_IRQ	!  81 0xc20 PIO1
-	.long	do_IRQ	!  82 0xc40 PIO2
-	.long	exception_error			!  83 0xc60
-	.long	exception_error			!  84 0xc80
-	.long	exception_error			!  85 0xca0
-	.long	exception_error			!  86 0xcc0
-	.long	exception_error			!  87 0xce0
-	.long	exception_error			!  88 0xd00
-	.long	exception_error			!  89 0xd20
-	.long	exception_error			!  90 0xd40
-	.long	exception_error			!  91 0xd60
-	.long	exception_error			!  92 0xd80
-	.long	exception_error			!  93 0xda0
-	.long	exception_error			!  94 0xdc0
-	.long	exception_error			!  95 0xde0
-	.long	exception_error			!  96 0xe00
-	.long	exception_error			!  97 0xe20
-	.long	exception_error			!  98 0xe40
-	.long	exception_error			!  99 0xe60
-	.long	exception_error			! 100 0xe80
-	.long	exception_error			! 101 0xea0
-	.long	exception_error			! 102 0xec0
-	.long	exception_error			! 103 0xee0
-	.long	exception_error			! 104 0xf00
-	.long	exception_error			! 105 0xf20
-	.long	exception_error			! 106 0xf40
-	.long	exception_error			! 107 0xf60
-	.long	exception_error			! 108 0xf80
-	.long	exception_error			! 109 0xfa0
-	.long	exception_error			! 110 0xfc0
-	.long	exception_error			! 111 0xfe0
-	.long	do_IRQ	! 112 0x1000 Mailbox
-	.long	exception_error			! 113 0x1020
-	.long	exception_error			! 114 0x1040
-	.long	exception_error			! 115 0x1060
-	.long	exception_error			! 116 0x1080
-	.long	exception_error			! 117 0x10a0
-	.long	exception_error			! 118 0x10c0
-	.long	exception_error			! 119 0x10e0
-	.long	exception_error			! 120 0x1100
-	.long	exception_error			! 121 0x1120
-	.long	exception_error			! 122 0x1140
-	.long	exception_error			! 123 0x1160
-	.long	exception_error			! 124 0x1180
-	.long	exception_error			! 125 0x11a0
-	.long	exception_error			! 126 0x11c0
-	.long	exception_error			! 127 0x11e0
-	.long	exception_error			! 128 0x1200
-	.long	exception_error			! 129 0x1220
-	.long	exception_error			! 130 0x1240
-	.long	exception_error			! 131 0x1260
-	.long	exception_error			! 132 0x1280
-	.long	exception_error			! 133 0x12a0
-	.long	exception_error			! 134 0x12c0
-	.long	exception_error			! 135 0x12e0
-	.long	exception_error			! 136 0x1300
-	.long	exception_error			! 137 0x1320
-	.long	exception_error			! 138 0x1340
-	.long	exception_error			! 139 0x1360
-	.long	do_IRQ	! 140 0x1380 EMPI INV_ADDR
-	.long	exception_error			! 141 0x13a0
-	.long	exception_error			! 142 0x13c0
-	.long	exception_error			! 143 0x13e0
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-	.long	do_IRQ	!  50 0x840
-	.long	do_IRQ	!  51 0x860
-	.long	do_IRQ	!  52 0x880
-	.long	do_IRQ	!  53 0x8a0
-	.long	do_IRQ	!  54 0x8c0
-	.long	do_IRQ	!  55 0x8e0
-	.long	do_IRQ	!  56 0x900
-	.long	do_IRQ	!  57 0x920
-	.long	do_IRQ	!  58 0x940
-	.long	do_IRQ	!  59 0x960
-	.long	do_IRQ	!  60 0x980
-	.long	do_IRQ	!  61 0x9a0
-	.long	do_IRQ	!  62 0x9c0
-	.long	do_IRQ	!  63 0x9e0
-	.long	do_IRQ	!  64 0xa00
-	.long	do_IRQ	!  65 0xa20
-	.long	do_IRQ	!  66 0xa4d
-	.long	do_IRQ	!  67 0xa60
-	.long	do_IRQ	!  68 0xa80
-	.long	do_IRQ	!  69 0xaa0
-	.long	do_IRQ	!  70 0xac0
-	.long	do_IRQ	!  71 0xae0
-	.long	do_IRQ	!  72 0xb00
-	.long	do_IRQ	!  73 0xb20
-	.long	do_IRQ	!  74 0xb40
-	.long	do_IRQ	!  75 0xb60
-	.long	do_IRQ	!  76 0xb80
-	.long	do_IRQ	!  77 0xba0
-	.long	do_IRQ	!  78 0xbc0
-	.long	do_IRQ	!  79 0xbe0
-	.long	do_IRQ	!  80 0xc00
-	.long	do_IRQ	!  81 0xc20
-	.long	do_IRQ	!  82 0xc40
-	.long	do_IRQ	!  83 0xc60
-	.long	do_IRQ	!  84 0xc80
-	.long	do_IRQ	!  85 0xca0
-	.long	do_IRQ	!  86 0xcc0
-	.long	do_IRQ	!  87 0xce0
-	.long	do_IRQ	!  88 0xd00
-	.long	do_IRQ	!  89 0xd20
-	.long	do_IRQ	!  90 0xd40
-	.long	do_IRQ	!  91 0xd60
-	.long	do_IRQ	!  92 0xd80
-	.long	do_IRQ	!  93 0xda0
-	.long	do_IRQ	!  94 0xdc0
-	.long	do_IRQ	!  95 0xde0
-	.long	do_IRQ	!  96 0xe00
-	.long	do_IRQ	!  97 0xe20
-	.long	do_IRQ	!  98 0xe40
-	.long	do_IRQ	!  99 0xe60
-	.long	do_IRQ	! 100 0xe80
-	.long	do_IRQ	! 101 0xea0
-	.long	do_IRQ	! 102 0xec0
-	.long	do_IRQ	! 103 0xee0
-	.long	do_IRQ	! 104 0xf00
-	.long	do_IRQ	! 105 0xf20
-	.long	do_IRQ	! 106 0xf40
-	.long	do_IRQ	! 107 0xf60
-	.long	do_IRQ	! 108 0xf80
-#endif
-#else
-	.long	exception_error		/* 400 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! RTC	ati
-	.long	do_IRQ	!	pri
-	.long	do_IRQ	!	cui
-	.long	exception_error
-	.long	exception_error		/* 500 */
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! WDT	iti	/* 560 */
-	.long	do_IRQ	! TMU-ch0
-	.long	do_IRQ	! TMU-ch1
-	.long	do_IRQ	! TMU-ch2
-	.long	do_IRQ	! ticpi2	/* 5E0 */
-	.long	do_IRQ	! 32 Hitachi UDI	/* 600 */
-	.long	exception_error
-	.long	do_IRQ	! 34 DMAC dmte0
-	.long	do_IRQ	! 35	  dmte1
-	.long	do_IRQ	! 36	  dmte2
-	.long	do_IRQ	! 37	  dmte3
-	.long	do_IRQ	! 38	  dmae
-	.long	exception_error			! 39	/* 6E0 */
-	.long	do_IRQ	! 40 SCIF-ch0 eri		/* 700 */
-	.long	do_IRQ	! 41	      rxi
-	.long	do_IRQ	! 42	      bri
-	.long	do_IRQ	! 43	      txi
-	.long	do_IRQ	! 44 DMAC dmte4		/* 780 */
-	.long	do_IRQ	! 45	  dmte5
-	.long	do_IRQ	! 46	  dmte6
-	.long	do_IRQ	! 47	  dmte7		/* 7E0 */
-#if defined(CONFIG_SH_FPU)
-	.long	do_fpu_state_restore	! 48	/* 800 */
-	.long	do_fpu_state_restore	! 49	/* 820 */
-#else
-	.long	exception_error
-	.long	exception_error
-#endif
-	.long	exception_error			/* 840 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! 56 CMT	/* 900 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! 60 HAC
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! PCI serr	/* A00 */
-	.long	do_IRQ	!     INTA
-	.long	do_IRQ	!     INTB
-	.long	do_IRQ	!     INTC
-	.long	do_IRQ	!     INTD
-	.long	do_IRQ	!     err
-	.long	do_IRQ	!     pwd3
-	.long	do_IRQ	!     pwd2
-	.long	do_IRQ	!     pwd1	/* B00 */
-	.long	do_IRQ	!     pwd0
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! SCIF-ch1 eri	/* B80 */
-	.long	do_IRQ	!	   rxi
-	.long	do_IRQ	!	   bri
-	.long	do_IRQ	!	   txi
-	.long	do_IRQ	! SIOF		/* C00 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! HSPI		/* C80 */
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! MMCIF	fatat	/* D00 */
-	.long	do_IRQ	!	tran
-	.long	do_IRQ	!	err
-	.long	do_IRQ	!	frdy
-	.long	do_IRQ	! DMAC dmint8	/* D80 */
-	.long	do_IRQ	!      dmint9
-	.long	do_IRQ	!      dmint10
-	.long	do_IRQ	!      dmint11
-	.long	do_IRQ	! TMU-ch3	/* E00 */
-	.long	do_IRQ	! TMU-ch4
-	.long	do_IRQ	! TMU-ch5
-	.long	exception_error
-	.long	do_IRQ	! SSI
-	.long	exception_error
-	.long	exception_error
-	.long	exception_error
-	.long	do_IRQ	! FLCTL	flste	/* F00 */
-	.long	do_IRQ	!	fltend
-	.long	do_IRQ	!	fltrq0
-	.long	do_IRQ	!	fltrq1
-	.long	do_IRQ	! GPIO gpioi0	/* F80 */
-	.long	do_IRQ	!      gpioi1
-	.long	do_IRQ	!      gpioi2
-	.long	do_IRQ	!      gpioi3
-#endif
-
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
index 97c571f..39aaefb 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/entry.S
@@ -1,9 +1,8 @@
-/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
- *
+/*
  *  linux/arch/sh/entry.S
  *
  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- *  Copyright (C) 2003  Paul Mundt
+ *  Copyright (C) 2003 - 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -78,7 +77,6 @@
 #define k3	r3
 #define k4	r4
 
-#define k_ex_code	r2_bank	/* r2_bank1 */
 #define g_imask		r6	/* r6_bank1 */
 #define k_g_imask	r6_bank	/* r6_bank1 */
 #define current		r7	/* r7_bank1 */
@@ -691,7 +689,7 @@
 0:
 #endif /* defined(CONFIG_KGDB_NMI) */
 	bra	handle_exception
-	 mov.l	@k2, k2
+	 mov	#-1, k2		! interrupt exception marker
 
 	.align	2
 1:	.long	EXPEVT
@@ -717,8 +715,7 @@
 	add	current, k1
 	mov	k1, r15		! change to kernel stack
 	!
-1:  	mov	#-1, k4
-	mov.l	2f, k1
+1:	mov.l	2f, k1
 	!
 #ifdef CONFIG_SH_DSP
 	mov.l	r2, @-r15		! Save r2, we need another reg
@@ -763,6 +760,8 @@
 #endif
 	! Save the user registers on the stack.
 	mov.l	k2, @-r15	! EXPEVT
+
+ 	mov	#-1, k4
 	mov.l	k4, @-r15	! set TRA (default: -1)
 	!
 	sts.l	macl, @-r15
@@ -797,8 +796,21 @@
 	mov.l	r2, @-r15
 	mov.l	r1, @-r15
 	mov.l	r0, @-r15
-	! Then, dispatch to the handler, according to the exception code.
-	stc	k_ex_code, r8
+
+	/*
+	 * This gets a bit tricky.. in the INTEVT case we don't want to use
+	 * the VBR offset as a destination in the jump call table, since all
+	 * of the destinations are the same. In this case, (interrupt) sets
+	 * a marker in r2 (now r2_bank since SR.RB changed), which we check
+	 * to determine the exception type. For all other exceptions, we
+	 * forcibly read EXPEVT from memory and fix up the jump address, in
+	 * the interrupt exception case we jump to do_IRQ() and defer the
+	 * INTEVT read until there. As a bonus, we can also clean up the SR.RB
+	 * checks that do_IRQ() was doing..
+	 */
+	stc	r2_bank, r8
+	cmp/pz	r8
+	bf	interrupt_exception
 	shlr2	r8
 	shlr	r8
 	mov.l	4f, r9
@@ -806,6 +818,8 @@
 	mov.l	@r9, r9
 	jmp	@r9
 	 nop
+	rts
+	 nop
 
 	.align	2
 1:	.long	0x00001000	! DSP=1
@@ -813,8 +827,17 @@
 3:	.long	0xcfffffff	! RB=0, BL=0
 4:	.long	exception_handling_table
 
+interrupt_exception:
+	mov.l	1f, r9
+	jmp	@r9
+	 nop
+	rts
+	 nop
+
+	.align 2
+1:	.long	do_IRQ
+
 	.align	2
 ENTRY(exception_none)
 	rts
 	 nop
-
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index c7ebd6a..acf2602 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -11,12 +11,15 @@
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
 #include <asm/cpu/mmu_context.h>
 
+atomic_t irq_err_count;
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves, it doesn't deserve
@@ -24,6 +27,7 @@
  */
 void ack_bad_irq(unsigned int irq)
 {
+	atomic_inc(&irq_err_count);
 	printk("unexpected IRQ trap at vector %02x\n", irq);
 }
 
@@ -47,8 +51,10 @@
 		if (!action)
 			goto unlock;
 		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "%10u ", kstat_irqs(i));
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq));
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -56,7 +62,9 @@
 		seq_putc(p, '\n');
 unlock:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
+	} else if (i == NR_IRQS)
+		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
+
 	return 0;
 }
 #endif
@@ -78,7 +86,8 @@
 		      unsigned long r6, unsigned long r7,
 		      struct pt_regs regs)
 {
-	int irq = r4;
+	struct pt_regs *old_regs = set_irq_regs(&regs);
+	int irq;
 #ifdef CONFIG_4KSTACKS
 	union irq_ctx *curctx, *irqctx;
 #endif
@@ -102,20 +111,9 @@
 #endif
 
 #ifdef CONFIG_CPU_HAS_INTEVT
-	__asm__ __volatile__ (
-#ifdef CONFIG_CPU_HAS_SR_RB
-		"stc	r2_bank, %0\n\t"
+	irq = (ctrl_inl(INTEVT) >> 5) - 16;
 #else
-		"mov.l	@%1, %0\n\t"
-#endif
-		"shlr2	%0\n\t"
-		"shlr2	%0\n\t"
-		"shlr	%0\n\t"
-		"add	#-16, %0\n\t"
-		: "=z" (irq), "=r" (r4)
-		: "1" (INTEVT)
-		: "memory"
-	);
+	irq = r4;
 #endif
 
 	irq = irq_demux(irq);
@@ -139,25 +137,25 @@
 
 		__asm__ __volatile__ (
 			"mov	%0, r4		\n"
-			"mov	%1, r5		\n"
 			"mov	r15, r9		\n"
-			"jsr	@%2		\n"
+			"jsr	@%1		\n"
 			/* swith to the irq stack */
-			" mov	%3, r15		\n"
+			" mov	%2, r15		\n"
 			/* restore the stack (ring zero) */
 			"mov	r9, r15		\n"
 			: /* no outputs */
-			: "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
+			: "r" (irq), "r" (generic_handle_irq), "r" (isp)
 			/* XXX: A somewhat excessive clobber list? -PFM */
 			: "memory", "r0", "r1", "r2", "r3", "r4",
 			  "r5", "r6", "r7", "r8", "t", "pr"
 		);
 	} else
 #endif
-		__do_IRQ(irq, &regs);
+		generic_handle_irq(irq);
 
 	irq_exit();
 
+	set_irq_regs(old_regs);
 	return 1;
 }
 
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 0b1d5dd..91516dc 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -5,6 +5,7 @@
  *  Copyright (C) 1995  Linus Torvalds
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
+ *		     Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  */
 
 /*
@@ -290,6 +291,24 @@
 static void
 ubc_set_tracing(int asid, unsigned long pc)
 {
+#if defined(CONFIG_CPU_SH4A)
+	unsigned long val;
+
+	val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE);
+	val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid));
+
+	ctrl_outl(val, UBC_CBR0);
+	ctrl_outl(pc,  UBC_CAR0);
+	ctrl_outl(0x0, UBC_CAMR0);
+	ctrl_outl(0x0, UBC_CBCR);
+
+	val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE);
+	ctrl_outl(val, UBC_CRR0);
+
+	/* Read UBC register that we writed last. For chekking UBC Register changed */
+	val = ctrl_inl(UBC_CRR0);
+
+#else	/* CONFIG_CPU_SH4A */
 	ctrl_outl(pc, UBC_BARA);
 
 #ifdef CONFIG_MMU
@@ -307,6 +326,7 @@
 		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
 		ctrl_outw(BRCR_PCBA, UBC_BRCR);
 	}
+#endif	/* CONFIG_CPU_SH4A */
 }
 
 /*
@@ -359,8 +379,13 @@
 #endif
 		ubc_set_tracing(asid, next->thread.ubc_pc);
 	} else {
+#if defined(CONFIG_CPU_SH4A)
+		ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
+		ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
+#else
 		ctrl_outw(0, UBC_BBRA);
 		ctrl_outw(0, UBC_BBRB);
+#endif
 	}
 
 	return prev;
@@ -460,8 +485,13 @@
 				 struct pt_regs regs)
 {
 	/* Clear tracing.  */
+#if defined(CONFIG_CPU_SH4A)
+	ctrl_outl(UBC_CBR_INIT, UBC_CBR0);
+	ctrl_outl(UBC_CRR_INIT, UBC_CRR0);
+#else
 	ctrl_outw(0, UBC_BBRA);
 	ctrl_outw(0, UBC_BBRB);
+#endif
 	current->thread.ubc_pc = 0;
 	ubc_usercnt -= 1;
 
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 450c68f..57e708d 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -47,6 +47,7 @@
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
+#ifndef CONFIG_GENERIC_TIME
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long seq;
@@ -99,6 +100,7 @@
 	return 0;
 }
 EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
 
 /* last time the RTC clock got updated */
 static long last_rtc_update;
@@ -107,13 +109,14 @@
  * handle_timer_tick() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-void handle_timer_tick(struct pt_regs *regs)
+void handle_timer_tick(void)
 {
 	do_timer(1);
 #ifndef CONFIG_SMP
-	update_process_times(user_mode(regs));
+	update_process_times(user_mode(get_irq_regs()));
 #endif
-	profile_tick(CPU_PROFILING, regs);
+	if (current->pid)
+		profile_tick(CPU_PROFILING);
 
 #ifdef CONFIG_HEARTBEAT
 	if (sh_mv.mv_heartbeat != NULL)
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 205816f..2492701 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -80,8 +80,7 @@
 	return count;
 }
 
-static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id,
-				       struct pt_regs *regs)
+static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
 	unsigned long timer_status;
 
@@ -98,7 +97,7 @@
 	 * locally disabled. -arca
 	 */
 	write_seqlock(&xtime_lock);
-	handle_timer_tick(regs);
+	handle_timer_tick();
 	write_sequnlock(&xtime_lock);
 
 	return IRQ_HANDLED;
@@ -111,60 +110,6 @@
 	.mask		= CPU_MASK_NONE,
 };
 
-/*
- * Hah!  We'll see if this works (switching from usecs to nsecs).
- */
-static unsigned long tmu_timer_get_frequency(void)
-{
-	u32 freq;
-	struct timespec ts1, ts2;
-	unsigned long diff_nsec;
-	unsigned long factor;
-
-	/* Setup the timer:  We don't want to generate interrupts, just
-	 * have it count down at its natural rate.
-	 */
-	ctrl_outb(0, TMU_TSTR);
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
-	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-#endif
-	ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
-	ctrl_outl(0xffffffff, TMU0_TCOR);
-	ctrl_outl(0xffffffff, TMU0_TCNT);
-
-	rtc_sh_get_time(&ts2);
-
-	do {
-		rtc_sh_get_time(&ts1);
-	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
-	/* actually start the timer */
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-
-	do {
-		rtc_sh_get_time(&ts2);
-	} while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
-	freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
-	if (ts2.tv_nsec < ts1.tv_nsec) {
-		ts2.tv_nsec += 1000000000;
-		ts2.tv_sec--;
-	}
-
-	diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
-
-	/* this should work well if the RTC has a precision of n Hz, where
-	 * n is an integer.  I don't think we have to worry about the other
-	 * cases. */
-	factor = (1000000000 + diff_nsec/2) / diff_nsec;
-
-	if (factor * diff_nsec > 1100000000 ||
-	    factor * diff_nsec <  900000000)
-		panic("weird RTC (diff_nsec %ld)", diff_nsec);
-
-	return freq * factor;
-}
-
 static void tmu_clk_init(struct clk *clk)
 {
 	u8 divisor = TMU0_TCR_INIT & 0x7;
@@ -232,12 +177,12 @@
 	.init		= tmu_timer_init,
 	.start		= tmu_timer_start,
 	.stop		= tmu_timer_stop,
-	.get_frequency	= tmu_timer_get_frequency,
+#ifndef CONFIG_GENERIC_TIME
 	.get_offset	= tmu_timer_get_offset,
+#endif
 };
 
 struct sys_timer tmu_timer = {
 	.name	= "tmu",
 	.ops	= &tmu_timer_ops,
 };
-
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index c81e6b6..38c82d8 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -28,6 +28,7 @@
 	split_page(page, order);
 
 	ret = page_address(page);
+	memset(ret, 0, size);
 	*handle = virt_to_phys(ret);
 
 	/*
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index b4e50ae..207f1b6 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -34,6 +34,7 @@
 #include <asm/pcic.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
+#include <asm/irq_regs.h>
 
 
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 0251cab..f5ee1ac 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -121,16 +121,6 @@
 	.index =	-1,
 };
 
-int obp_system_intr(void)
-{
-	if (boot_flags & BOOTME_DEBUG) {
-		printk("OBP: system interrupted\n");
-		prom_halt();
-		return 1;
-	}
-	return 0;
-}
-
 /* 
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 346c19a..1dd78c8 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -36,11 +36,11 @@
 
   . = ALIGN(4096);
   __init_begin = .;
+  _sinittext = .;
   .init.text : { 
-	_sinittext = .;
 	*(.init.text)
-	_einittext = .;
   }
+  _einittext = .;
   __init_text_end = .;
   .init.data : { *(.init.data) }
   . = ALIGN(16);
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index b27a506..0df7121 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -402,7 +402,7 @@
 	srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
 }
 
-void srmmu_nocache_init(void)
+void __init srmmu_nocache_init(void)
 {
 	unsigned int bitmap_bits;
 	pgd_t *pgd;
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 9582874..cc8ad48 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -91,16 +91,6 @@
 {
 }
 
-int obp_system_intr(void)
-{
-	if (boot_flags & BOOTME_DEBUG) {
-		printk("OBP: system interrupted\n");
-		prom_halt();
-		return 1;
-	}
-	return 0;
-}
-
 /* 
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index c3cdcab..44b55f8 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -660,7 +660,7 @@
 		}
 		if (old_vector >= 0) {
 			int old_cpu;
-			for_each_cpu_mask(old_cpu, domain)
+			for_each_cpu_mask(old_cpu, irq_domain[irq])
 				per_cpu(vector_irq, old_cpu)[old_vector] = -1;
 		}
 		for_each_cpu_mask(new_cpu, domain)
diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c
index 044e852..414caf0 100644
--- a/arch/x86_64/kernel/vsmp.c
+++ b/arch/x86_64/kernel/vsmp.c
@@ -14,6 +14,7 @@
 #include <linux/pci_ids.h>
 #include <linux/pci_regs.h>
 #include <asm/pci-direct.h>
+#include <asm/io.h>
 
 static int __init vsmp_init(void)
 {
diff --git a/block/elevator.c b/block/elevator.c
index 487dd3d..8ccd163 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -93,21 +93,18 @@
 
 static struct elevator_type *elevator_find(const char *name)
 {
-	struct elevator_type *e = NULL;
+	struct elevator_type *e;
 	struct list_head *entry;
 
 	list_for_each(entry, &elv_list) {
-		struct elevator_type *__e;
 
-		__e = list_entry(entry, struct elevator_type, list);
+		e = list_entry(entry, struct elevator_type, list);
 
-		if (!strcmp(__e->elevator_name, name)) {
-			e = __e;
-			break;
-		}
+		if (!strcmp(e->elevator_name, name))
+			return e;
 	}
 
-	return e;
+	return NULL;
 }
 
 static void elevator_put(struct elevator_type *e)
@@ -1088,7 +1085,7 @@
 	struct list_head *entry;
 	int len = 0;
 
-	spin_lock_irq(q->queue_lock);
+	spin_lock_irq(&elv_list_lock);
 	list_for_each(entry, &elv_list) {
 		struct elevator_type *__e;
 
@@ -1098,7 +1095,7 @@
 		else
 			len += sprintf(name+len, "%s ", __e->elevator_name);
 	}
-	spin_unlock_irq(q->queue_lock);
+	spin_unlock_irq(&elv_list_lock);
 
 	len += sprintf(len+name, "\n");
 	return len;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 69bbb62..bddfebd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -597,7 +597,7 @@
 	struct cdrom_info *cd = drive->driver_data;
 
 	ide_init_drive_cmd(rq);
-	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+	rq->cmd_type = REQ_TYPE_ATA_PC;
 	rq->rq_disk = cd->disk;
 }
 
@@ -716,7 +716,7 @@
 		ide_error(drive, "request sense failure", stat);
 		return 1;
 
-	} else if (blk_pc_request(rq)) {
+	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
 		/* All other functions, except for READ. */
 		unsigned long flags;
 
@@ -2023,7 +2023,8 @@
 		}
 		info->last_block = block;
 		return action;
-	} else if (rq->cmd_type == REQ_TYPE_SENSE) {
+	} else if (rq->cmd_type == REQ_TYPE_SENSE ||
+		   rq->cmd_type == REQ_TYPE_ATA_PC) {
 		return cdrom_do_packet_command(drive);
 	} else if (blk_pc_request(rq)) {
 		return cdrom_do_block_pc(drive, rq);
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 8b6efcc..143302a 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -160,7 +160,7 @@
 	tmp |= RCR1_CIE;
 	writeb(tmp, rtc->regbase + RCR1);
 
-	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, SA_INTERRUPT,
+	ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
 			  "sh-rtc period", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
@@ -168,7 +168,7 @@
 		return ret;
 	}
 
-	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, SA_INTERRUPT,
+	ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
 			  "sh-rtc carry", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
@@ -177,7 +177,7 @@
 		goto err_bad_carry;
 	}
 
-	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT,
+	ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, IRQF_DISABLED,
 			  "sh-rtc alarm", dev);
 	if (unlikely(ret)) {
 		dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index d27e4f6..0d3660c 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -4,10 +4,8 @@
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
  */
 
-#include <linux/kernel.h>
 #include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/delay.h>
 #include <asm/oplib.h>
 #include <asm/ebus.h>
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 728a133..6b6a855 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -20,16 +20,12 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/init.h>
 #include <linux/kthread.h>
-#include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
+#include <linux/syscalls.h>
 
 #include <asm/ebus.h>
 #include <asm/uaccess.h>
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 266aa32..cfcc3ca 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -808,7 +808,7 @@
 		}
 
 		if (request_irq(port->irqs[0], sci_mpxed_interrupt,
-				SA_INTERRUPT, "sci", port)) {
+				IRQF_DISABLED, "sci", port)) {
 			printk(KERN_ERR "sci: Cannot allocate irq.\n");
 			return -ENODEV;
 		}
@@ -817,7 +817,7 @@
 			if (!port->irqs[i])
 				continue;
 			if (request_irq(port->irqs[i], handlers[i],
-					SA_INTERRUPT, desc[i], port)) {
+					IRQF_DISABLED, desc[i], port)) {
 				printk(KERN_ERR "sci: Cannot allocate irq.\n");
 				return -ENODEV;
 			}
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 73dd2ee..b2cc703 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1182,7 +1182,7 @@
 	return 0;
 }
 
-static struct console sunzilog_console = {
+static struct console sunzilog_console_ops = {
 	.name	=	"ttyS",
 	.write	=	sunzilog_console_write,
 	.device	=	uart_console_device,
@@ -1208,10 +1208,10 @@
 	if (i == NUM_CHANNELS)
 		return NULL;
 
-	sunzilog_console.index = i;
+	sunzilog_console_ops.index = i;
 	sunzilog_port_table[i].flags |= SUNZILOG_FLAG_IS_CONS;
 
-	return &sunzilog_console;
+	return &sunzilog_console_ops;
 }
 
 #else
diff --git a/fs/Kconfig b/fs/Kconfig
index db4d133..6a3df05 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1986,7 +1986,7 @@
 config CIFS_UPCALL
 	  bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
 	  depends on CIFS_EXPERIMENTAL
-	  select CONNECTOR
+	  depends on CONNECTOR
 	  help
 	    Enables an upcall mechanism for CIFS which will be used to contact
 	    userspace helper utilities to provide SPNEGO packaged Kerberos
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 06435f36..5610061 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1152,7 +1152,7 @@
 static int dump_seek(struct file *file, loff_t off)
 {
 	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-		if (file->f_op->llseek(file, off, 1) != off)
+		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
 			return 0;
 	} else {
 		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index d0776ac..5eff35d 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -31,8 +31,8 @@
 } __attribute__((packed));
 
 /* everyone */
-extern const struct cifs_sid sid_everyone;
+/* extern const struct cifs_sid sid_everyone;*/
 /* group users */
-extern const struct cifs_sid sid_user;
+/* extern const struct cifs_sid sid_user;*/
 
 #endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
index 03e359b..152fa2d 100644
--- a/fs/cifs/cifsencrypt.h
+++ b/fs/cifs/cifsencrypt.h
@@ -27,8 +27,6 @@
 /* smbdes.c */
 extern void E_P16(unsigned char *p14, unsigned char *p16);
 extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
-extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
-extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
 
 
 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c00c654..84976cd 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -63,6 +63,7 @@
 struct task_struct * oplockThread = NULL;
 extern struct task_struct * dnotifyThread; /* remove sparse warning */
 struct task_struct * dnotifyThread = NULL;
+static struct super_operations cifs_super_ops; 
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -198,10 +199,12 @@
     /* Only need to call the old QFSInfo if failed
     on newer one */
     if(rc)
-	rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+	if(pTcon->ses->capabilities & CAP_NT_SMBS)
+		rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
 
-	/* Old Windows servers do not support level 103, retry with level 
-	   one if old server failed the previous call */ 
+	/* Some old Windows servers also do not support level 103, retry with
+	   older level one if old server failed the previous call or we
+	   bypassed it because we detected that this was an older LANMAN sess */
 	if(rc)
 		rc = SMBOldQFSInfo(xid, pTcon, buf);
 	/*     
@@ -435,13 +438,21 @@
 	return;
 }
 
+#ifdef CONFIG_CIFS_STATS2
+static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
+{
+	/* BB FIXME */
+	return 0;
+}
+#endif
+
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
 	*flags |= MS_NODIRATIME;
 	return 0;
 }
 
-struct super_operations cifs_super_ops = {
+static struct super_operations cifs_super_ops = {
 	.read_inode = cifs_read_inode,
 	.put_super = cifs_put_super,
 	.statfs = cifs_statfs,
@@ -454,6 +465,9 @@
 	.show_options = cifs_show_options,
 	.umount_begin   = cifs_umount_begin,
 	.remount_fs = cifs_remount,
+#ifdef CONFIG_CIFS_STATS2
+	.show_stats = cifs_show_stats,
+#endif
 };
 
 static int
@@ -495,7 +509,7 @@
 static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
 	/* origin == SEEK_END => we must revalidate the cached file length */
-	if (origin == 2) {
+	if (origin == SEEK_END) {
 		int retval = cifs_revalidate(file->f_dentry);
 		if (retval < 0)
 			return (loff_t)retval;
@@ -903,7 +917,7 @@
 #ifdef CONFIG_PROC_FS
 	cifs_proc_init();
 #endif
-	INIT_LIST_HEAD(&GlobalServerList);	/* BB not implemented yet */
+/*	INIT_LIST_HEAD(&GlobalServerList);*/	/* BB not implemented yet */
 	INIT_LIST_HEAD(&GlobalSMBSessionList);
 	INIT_LIST_HEAD(&GlobalTreeConnectionList);
 	INIT_LIST_HEAD(&GlobalOplock_Q);
@@ -931,6 +945,7 @@
 	GlobalCurrentXid = 0;
 	GlobalTotalActiveXid = 0;
 	GlobalMaxActiveXid = 0;
+	memset(Local_System_Name, 0, 15);
 	rwlock_init(&GlobalSMBSeslock);
 	spin_lock_init(&GlobalMid_Lock);
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index bea875d..a243f779 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,7 +36,7 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-extern struct super_operations cifs_super_ops;
+/* extern struct super_operations cifs_super_ops;*/
 extern void cifs_read_inode(struct inode *);
 extern void cifs_delete_inode(struct inode *);
 /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b24006c..74d3ccb 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -153,7 +153,7 @@
 	char sessid[4];		/* unique token id for this session */
 	/* (returned on Negotiate */
 	int capabilities; /* allow selective disabling of caps by smb sess */
-	__u16 timeZone;
+	int timeAdj;  /* Adjust for difference in server time zone in sec */
 	__u16 CurrentMid;         /* multiplex id - rotating counter */
 	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 	/* 16th byte of RFC1001 workstation name is always null */
@@ -203,9 +203,14 @@
 	char * domainName;
 	char * password;
 };
-/* session flags */
+/* no more than one of the following three session flags may be set */
 #define CIFS_SES_NT4 1
-
+#define CIFS_SES_OS2 2
+#define CIFS_SES_W9X 4
+/* following flag is set for old servers such as OS2 (and Win95?)
+   which do not negotiate NTLM or POSIX dialects, but instead
+   negotiate one of the older LANMAN dialects */
+#define CIFS_SES_LANMAN 8
 /*
  * there is one of these for each connection to a resource on a particular
  * session 
@@ -512,7 +517,8 @@
  * This list helps improve performance and eliminate the messages indicating
  * that we had a communications error talking to the server in this list. 
  */
-GLOBAL_EXTERN struct servers_not_supported *NotSuppList;	/*@z4a */
+/* Feature not supported */
+/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */
 
 /*
  * The following is a hash table of all the users we know about.
@@ -568,7 +574,6 @@
 GLOBAL_EXTERN unsigned int extended_security;	/* if on, session setup sent 
 				with more secure ntlmssp2 challenge/resp */
 GLOBAL_EXTERN unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
-GLOBAL_EXTERN unsigned int secFlags;
 GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
 GLOBAL_EXTERN unsigned int CIFSMaxBufSize;  /* max size not including hdr */
 GLOBAL_EXTERN unsigned int cifs_min_rcv;    /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 81df2bf..6df9dad 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -26,7 +26,8 @@
 
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 #define LANMAN_PROT 0
-#define CIFS_PROT   1
+#define LANMAN2_PROT 1
+#define CIFS_PROT   2
 #else
 #define CIFS_PROT   0
 #endif
@@ -408,6 +409,8 @@
 
 /* Dialect index is 13 for LANMAN */
 
+#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
+
 typedef struct lanman_neg_rsp {
 	struct smb_hdr hdr;	/* wct = 13 */
 	__le16 DialectIndex;
@@ -417,7 +420,10 @@
 	__le16 MaxNumberVcs;
 	__le16 RawMode;
 	__le32 SessionKey;
-	__le32 ServerTime;
+	struct {
+		__le16 Time;
+		__le16 Date;
+	} __attribute__((packed)) SrvTime;
 	__le16 ServerTimeZone;
 	__le16 EncryptionKeyLength;
 	__le16 Reserved;
@@ -674,7 +680,7 @@
 typedef struct smb_com_close_req {
 	struct smb_hdr hdr;	/* wct = 3 */
 	__u16 FileID;
-	__u32 LastWriteTime;	/* should be zero */
+	__u32 LastWriteTime;	/* should be zero or -1 */
 	__u16 ByteCount;	/* 0 */
 } __attribute__((packed)) CLOSE_REQ;
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b35c55c..f1f8225 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,12 +50,12 @@
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
 			struct kvec *, int /* nvec to send */, 
 			int * /* type of buf returned */ , const int long_op);
-extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
+extern int SendReceiveBlockingLock(const unsigned int /* xid */ , 
+					struct cifsTconInfo *,
 				struct smb_hdr * /* input */ ,
 				struct smb_hdr * /* out */ ,
 				int * /* bytes returned */);
-extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
-extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
+extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
 extern int is_size_safe_to_change(struct cifsInodeInfo *);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
@@ -80,6 +80,9 @@
 extern void DeleteOplockQEntry(struct oplock_q_entry *);
 extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
 extern u64 cifs_UnixTimeToNT(struct timespec);
+extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
+extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
+
 extern int cifs_get_inode_info(struct inode **pinode,
 			const unsigned char *search_path, 
 			FILE_ALL_INFO * pfile_info,
@@ -116,6 +119,7 @@
 extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 			const unsigned char *searchName,
 			FILE_ALL_INFO * findData,
+			int legacy /* whether to use old info level */,
 			const struct nls_table *nls_codepage, int remap);
 extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *searchName,
@@ -279,8 +283,6 @@
 extern struct cifsTconInfo *tconInfoAlloc(void);
 extern void tconInfoFree(struct cifsTconInfo *);
 
-extern int cifs_reconnect(struct TCP_Server_Info *server);
-
 extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 075d8fb..5dc5a96 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -46,6 +46,7 @@
 } protocols[] = {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 	{LANMAN_PROT, "\2LM1.2X002"},
+	{LANMAN2_PROT, "\2LANMAN2.1"},
 #endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
 	{POSIX_PROT, "\2POSIX 2"},
@@ -58,6 +59,7 @@
 } protocols[] = {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 	{LANMAN_PROT, "\2LM1.2X002"},
+	{LANMAN2_PROT, "\2LANMAN2.1"},
 #endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
 	{BAD_PROT, "\2"}
@@ -67,13 +69,13 @@
 /* define the number of elements in the cifs dialect array */
 #ifdef CONFIG_CIFS_POSIX
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 3
+#define CIFS_NUM_PROT 4
 #else
 #define CIFS_NUM_PROT 2
 #endif /* CIFS_WEAK_PW_HASH */
 #else /* not posix */
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-#define CIFS_NUM_PROT 2
+#define CIFS_NUM_PROT 3
 #else
 #define CIFS_NUM_PROT 1
 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
@@ -446,7 +448,9 @@
 		goto neg_err_exit;
 #ifdef CONFIG_CIFS_WEAK_PW_HASH 
 	} else if((pSMBr->hdr.WordCount == 13)
-			&& (pSMBr->DialectIndex == LANMAN_PROT)) {
+			&& ((pSMBr->DialectIndex == LANMAN_PROT)
+				|| (pSMBr->DialectIndex == LANMAN2_PROT))) {
+		__s16 tmp;
 		struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
 
 		if((secFlags & CIFSSEC_MAY_LANMAN) || 
@@ -472,12 +476,44 @@
 			server->maxRw = 0;/* we do not need to use raw anyway */
 			server->capabilities = CAP_MPX_MODE;
 		}
-		server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
+		tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
+		if (tmp == -1) {
+			/* OS/2 often does not set timezone therefore
+			 * we must use server time to calc time zone.
+			 * Could deviate slightly from the right zone.
+			 * Smallest defined timezone difference is 15 minutes
+			 * (i.e. Nepal).  Rounding up/down is done to match
+			 * this requirement.
+			 */
+			int val, seconds, remain, result;
+			struct timespec ts, utc;
+			utc = CURRENT_TIME;
+			ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
+						le16_to_cpu(rsp->SrvTime.Time));
+			cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
+				(int)ts.tv_sec, (int)utc.tv_sec, 
+				(int)(utc.tv_sec - ts.tv_sec)));
+			val = (int)(utc.tv_sec - ts.tv_sec);
+			seconds = val < 0 ? -val : val;
+			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
+			remain = seconds % MIN_TZ_ADJ;
+			if(remain >= (MIN_TZ_ADJ / 2))
+				result += MIN_TZ_ADJ;
+			if(val < 0)
+				result = - result;
+			server->timeAdj = result;
+		} else {
+			server->timeAdj = (int)tmp;
+			server->timeAdj *= 60; /* also in seconds */
+		}
+		cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
+
 
 		/* BB get server time for time conversions and add
 		code to use it and timezone since this is not UTC */	
 
-		if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
+		if (rsp->EncryptionKeyLength == 
+				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
 			memcpy(server->cryptKey, rsp->EncryptionKey,
 				CIFS_CRYPTO_KEY_SIZE);
 		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
@@ -531,7 +567,8 @@
 	cFYI(0, ("Max buf = %d", ses->server->maxBuf));
 	GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
-	server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
+	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
+	server->timeAdj *= 60;
 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
 		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
 		       CIFS_CRYPTO_KEY_SIZE);
@@ -1617,7 +1654,7 @@
 	pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
 
 	pSMB->FileID = (__u16) smb_file_id;
-	pSMB->LastWriteTime = 0;
+	pSMB->LastWriteTime = 0xFFFFFFFF;
 	pSMB->ByteCount = 0;
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2773,9 +2810,11 @@
 
 
 /* security id for everyone */
-const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
+const static struct cifs_sid sid_everyone = 
+		{1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
 /* group users */
-const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
+const static struct cifs_sid sid_user = 
+		{1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
 
 /* Convert CIFS ACL to POSIX form */
 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
@@ -2856,7 +2895,6 @@
 	return rc;
 }
 
-
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -2898,7 +2936,16 @@
 	if (rc) {
 		cFYI(1, ("Send error in QueryInfo = %d", rc));
 	} else if (pFinfo) {            /* decode response */
+		struct timespec ts;
+		__u32 time = le32_to_cpu(pSMBr->last_write_time);
+		/* BB FIXME - add time zone adjustment BB */
 		memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
+		ts.tv_nsec = 0;
+		ts.tv_sec = time;
+		/* decode time fields */
+		pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
+		pFinfo->LastWriteTime = pFinfo->ChangeTime;
+		pFinfo->LastAccessTime = 0;
 		pFinfo->AllocationSize =
 			cpu_to_le64(le32_to_cpu(pSMBr->size));
 		pFinfo->EndOfFile = pFinfo->AllocationSize;
@@ -2922,6 +2969,7 @@
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 		 const unsigned char *searchName,
 		 FILE_ALL_INFO * pFindData,
+		 int legacy /* old style infolevel */,
 		 const struct nls_table *nls_codepage, int remap)
 {
 /* level 263 SMB_QUERY_FILE_ALL_INFO */
@@ -2970,7 +3018,10 @@
 	byte_count = params + 1 /* pad */ ;
 	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
-	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+	if(legacy)
+		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+	else
+		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
 	pSMB->Reserved4 = 0;
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
@@ -2982,13 +3033,24 @@
 	} else {		/* decode response */
 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
-		if (rc || (pSMBr->ByteCount < 40)) 
+		if (rc) /* BB add auto retry on EOPNOTSUPP? */
+			rc = -EIO;
+		else if (!legacy && (pSMBr->ByteCount < 40)) 
 			rc = -EIO;	/* bad smb */
+		else if(legacy && (pSMBr->ByteCount < 24))
+			rc = -EIO;  /* 24 or 26 expected but we do not read last field */
 		else if (pFindData){
+			int size;
 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			if(legacy) /* we do not read the last field, EAsize, fortunately
+					   since it varies by subdialect and on Set vs. Get, is  
+					   two bytes or 4 bytes depending but we don't care here */
+				size = sizeof(FILE_INFO_STANDARD);
+			else
+				size = sizeof(FILE_ALL_INFO);
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       data_offset, sizeof (FILE_ALL_INFO));
+			       data_offset, size);
 		} else
 		    rc = -ENOMEM;
 	}
@@ -3613,6 +3675,14 @@
 		strncpy(pSMB->RequestFileName, searchName, name_len);
 	}
 
+	if(ses->server) {
+		if(ses->server->secMode &
+		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
+
+        pSMB->hdr.Uid = ses->Suid;
+
 	params = 2 /* level */  + name_len /*includes null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c787620..4093d53 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -109,7 +109,7 @@
 	 * wake up waiters on reconnection? - (not needed currently)
 	 */
 
-int
+static int
 cifs_reconnect(struct TCP_Server_Info *server)
 {
 	int rc = 0;
@@ -771,13 +771,18 @@
 	separator[0] = ',';
 	separator[1] = 0; 
 
-	memset(vol->source_rfc1001_name,0x20,15);
-	for(i=0;i < strnlen(utsname()->nodename,15);i++) {
-		/* does not have to be a perfect mapping since the field is
-		informational, only used for servers that do not support
-		port 445 and it can be overridden at mount time */
-		vol->source_rfc1001_name[i] = 
-			toupper(utsname()->nodename[i]);
+	if (Local_System_Name[0] != 0)
+		memcpy(vol->source_rfc1001_name, Local_System_Name,15);
+	else {
+		char *nodename = utsname()->nodename;
+		int n = strnlen(nodename,15);
+		memset(vol->source_rfc1001_name,0x20,15);
+		for(i=0 ; i < n ; i++) {
+			/* does not have to be perfect mapping since field is
+			informational, only used for servers that do not support
+			port 445 and it can be overridden at mount time */
+			vol->source_rfc1001_name[i] = toupper(nodename[i]);
+		}
 	}
 	vol->source_rfc1001_name[15] = 0;
 	/* null target name indicates to use *SMBSERVR default called name
@@ -3215,7 +3220,9 @@
 			}
 			/* else do not bother copying these informational fields */
 		}
-		if(smb_buffer_response->WordCount == 3)
+		if((smb_buffer_response->WordCount == 3) ||
+			 (smb_buffer_response->WordCount == 7))
+			/* field is in same location */
 			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
 		else
 			tcon->Flags = 0;
@@ -3312,19 +3319,21 @@
 		first_time = 1;
 	}
 	if (!rc) {
+		pSesInfo->flags = 0;
 		pSesInfo->capabilities = pSesInfo->server->capabilities;
 		if(linuxExtEnabled == 0)
 			pSesInfo->capabilities &= (~CAP_UNIX);
 	/*	pSesInfo->sequence_number = 0;*/
-		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
+		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
-			pSesInfo->server->timeZone));
+			pSesInfo->server->timeAdj));
 		if(experimEnabled < 2)
 			rc = CIFS_SessSetup(xid, pSesInfo,
 					    first_time, nls_info);
 		else if (extended_security
-				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+				&& (pSesInfo->capabilities 
+					& CAP_EXTENDED_SECURITY)
 				&& (pSesInfo->server->secType == NTLMSSP)) {
 			rc = -EOPNOTSUPP;
 		} else if (extended_security
@@ -3338,7 +3347,7 @@
 			if (!rc) {
 				if(ntlmv2_flag) {
 					char * v2_response;
-					cFYI(1,("Can use more secure NTLM version 2 password hash"));
+					cFYI(1,("more secure NTLM ver2 hash"));
 					if(CalcNTLMv2_partial_mac_key(pSesInfo, 
 						nls_info)) {
 						rc = -ENOMEM;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 6b90ef9..35d54bb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -337,6 +337,7 @@
 		pfindData = (FILE_ALL_INFO *)buf;
 		/* could do find first instead but this returns more info */
 		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+			      0 /* not legacy */,
 			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
 		/* BB optimize code so we do not make the above call
@@ -384,8 +385,10 @@
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			if (*pinode == NULL)
+			if (*pinode == NULL) {
+				kfree(buf);
 				return -ENOMEM;
+			}
 			/* Is an i_ino of zero legal? Can we use that to check
 			   if the server supports returning inode numbers?  Are
 			   there other sanity checks we can use to ensure that
@@ -431,8 +434,11 @@
 		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 
 		/* Linux can not store file creation time so ignore it */
-		inode->i_atime =
-		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+		if(pfindData->LastAccessTime)
+			inode->i_atime = cifs_NTtimeToUnix
+				(le64_to_cpu(pfindData->LastAccessTime));
+		else /* do not need to use current_fs_time - time not stored */
+			inode->i_atime = CURRENT_TIME;
 		inode->i_mtime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
 		inode->i_ctime =
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index a57f5d6..0bee8b7 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -254,7 +254,11 @@
 				tmpbuffer,
 				len - 1,
 				cifs_sb->local_nls);
-	else {
+	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+		cERROR(1,("SFU style symlinks not implemented yet"));
+		/* add open and read as in fs/cifs/inode.c */
+	
+	} else {
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
 				OPEN_REPARSE_POINT,&fid, &oplock, NULL, 
 				cifs_sb->local_nls, 
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
index 7aa2349..ccebf9b 100644
--- a/fs/cifs/md5.c
+++ b/fs/cifs/md5.c
@@ -252,10 +252,11 @@
 	buf[3] += d;
 }
 
+#if 0   /* currently unused */
 /***********************************************************************
  the rfc 2104 version of hmac_md5 initialisation.
 ***********************************************************************/
-void
+static void
 hmac_md5_init_rfc2104(unsigned char *key, int key_len,
 		      struct HMACMD5Context *ctx)
 {
@@ -289,6 +290,7 @@
 	MD5Init(&ctx->ctx);
 	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
 }
+#endif
 
 /***********************************************************************
  the microsoft version of hmac_md5 initialisation.
@@ -350,7 +352,8 @@
  single function to calculate an HMAC MD5 digest from data.
  use the microsoft hmacmd5 init method because the key is 16 bytes.
 ************************************************************/
-void
+#if 0 /* currently unused */
+static void
 hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
 	 unsigned char *digest)
 {
@@ -361,3 +364,4 @@
 	}
 	hmac_md5_final(digest, &ctx);
 }
+#endif
diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h
index 00e1c53..f7d4f41 100644
--- a/fs/cifs/md5.h
+++ b/fs/cifs/md5.h
@@ -27,12 +27,12 @@
 
 /* The following definitions come from lib/hmacmd5.c  */
 
-void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
-			struct HMACMD5Context *ctx);
+/* void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+			struct HMACMD5Context *ctx);*/
 void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
 			struct HMACMD5Context *ctx);
 void hmac_md5_update(const unsigned char *text, int text_len,
 			struct HMACMD5Context *ctx);
 void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
-void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
-			unsigned char *digest);
+/* void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+			unsigned char *digest);*/
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 22c937e..bbc9cd3 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -389,7 +389,7 @@
 	return;
 }
 
-int
+static int
 checkSMBhdr(struct smb_hdr *smb, __u16 mid)
 {
 	/* Make sure that this really is an SMB, that it is a response, 
@@ -418,26 +418,42 @@
 }
 
 int
-checkSMB(struct smb_hdr *smb, __u16 mid, int length)
+checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
 {
 	__u32 len = smb->smb_buf_length;
 	__u32 clc_len;  /* calculated length */
 	cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
-	if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
-	    (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
-		if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
-			if (((unsigned int)length >= 
-				sizeof (struct smb_hdr) - 1)
+
+	if (length < 2 + sizeof (struct smb_hdr)) {
+		if ((length >= sizeof (struct smb_hdr) - 1)
 			    && (smb->Status.CifsError != 0)) {
-				smb->WordCount = 0;
-				/* some error cases do not return wct and bcc */
+			smb->WordCount = 0;
+			/* some error cases do not return wct and bcc */
+			return 0;
+		} else if ((length == sizeof(struct smb_hdr) + 1) && 
+				(smb->WordCount == 0)) {
+			char * tmp = (char *)smb;
+			/* Need to work around a bug in two servers here */
+			/* First, check if the part of bcc they sent was zero */
+			if (tmp[sizeof(struct smb_hdr)] == 0) {
+				/* some servers return only half of bcc
+				 * on simple responses (wct, bcc both zero)
+				 * in particular have seen this on
+				 * ulogoffX and FindClose. This leaves
+				 * one byte of bcc potentially unitialized
+				 */
+				/* zero rest of bcc */
+				tmp[sizeof(struct smb_hdr)+1] = 0;
 				return 0;
-			} else {
-				cERROR(1, ("Length less than smb header size"));
 			}
+			cERROR(1,("rcvd invalid byte count (bcc)"));
+		} else {
+			cERROR(1, ("Length less than smb header size"));
 		}
-		if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-			cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+		return 1;
+	}
+	if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
 				   smb->Mid));
 		return 1;
 	}
@@ -446,7 +462,7 @@
 		return 1;
 	clc_len = smbCalcSize_LE(smb);
 
-	if(4 + len != (unsigned int)length) {
+	if(4 + len != length) {
 		cERROR(1, ("Length read does not match RFC1001 length %d",len));
 		return 1;
 	}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index ce87550..992e80e 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -909,3 +909,61 @@
 	/* Convert to 100ns intervals and then add the NTFS time offset. */
 	return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
 }
+
+static int total_days_of_prev_months[] =
+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+
+__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
+{
+	return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
+}
+
+struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
+{
+	struct timespec ts;
+	int sec, min, days, month, year;
+	SMB_TIME * st = (SMB_TIME *)&time;
+	SMB_DATE * sd = (SMB_DATE *)&date;
+
+	cFYI(1,("date %d time %d",date, time));
+
+	sec = 2 * st->TwoSeconds;
+	min = st->Minutes;
+	if((sec > 59) || (min > 59))
+		cERROR(1,("illegal time min %d sec %d", min, sec));
+	sec += (min * 60);
+	sec += 60 * 60 * st->Hours;
+	if(st->Hours > 24)
+		cERROR(1,("illegal hours %d",st->Hours));
+	days = sd->Day;
+	month = sd->Month;
+	if((days > 31) || (month > 12))
+		cERROR(1,("illegal date, month %d day: %d", month, days));
+	month -= 1;
+	days += total_days_of_prev_months[month];
+	days += 3652; /* account for difference in days between 1980 and 1970 */
+	year = sd->Year;
+	days += year * 365;
+	days += (year/4); /* leap year */
+	/* generalized leap year calculation is more complex, ie no leap year
+	for years/100 except for years/400, but since the maximum number for DOS
+	 year is 2**7, the last year is 1980+127, which means we need only
+	 consider 2 special case years, ie the years 2000 and 2100, and only
+	 adjust for the lack of leap year for the year 2100, as 2000 was a 
+	 leap year (divisable by 400) */
+	if(year >= 120)  /* the year 2100 */
+		days = days - 1;  /* do not count leap year for the year 2100 */
+
+	/* adjust for leap year where we are still before leap day */
+	if(year != 120)
+		days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
+	sec += 24 * 60 * 60 * days; 
+
+	ts.tv_sec = sec;
+
+	/* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
+
+	ts.tv_nsec = 0;
+	return ts;
+} 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b27b345..b5b0a2a 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -106,6 +106,17 @@
 	return rc;
 }
 
+static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode)
+{
+	if((tcon) && (tcon->ses) && (tcon->ses->server)) {
+		inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;
+		inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;
+		inode->i_atime.tv_sec += tcon->ses->server->timeAdj;
+	}
+	return;
+}
+
+
 static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 		char * buf, int *pobject_type, int isNewInode)
 {
@@ -135,16 +146,23 @@
 		tmp_inode->i_ctime =
 		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
 	} else { /* legacy, OS2 and DOS style */
+/*		struct timespec ts;*/
 		FIND_FILE_STANDARD_INFO * pfindData = 
 			(FIND_FILE_STANDARD_INFO *)buf;
 
+		tmp_inode->i_mtime = cnvrtDosUnixTm(
+				le16_to_cpu(pfindData->LastWriteDate),
+				le16_to_cpu(pfindData->LastWriteTime));
+		tmp_inode->i_atime = cnvrtDosUnixTm(
+				le16_to_cpu(pfindData->LastAccessDate),
+				le16_to_cpu(pfindData->LastAccessTime));
+                tmp_inode->i_ctime = cnvrtDosUnixTm(
+                                le16_to_cpu(pfindData->LastWriteDate),
+                                le16_to_cpu(pfindData->LastWriteTime));
+		AdjustForTZ(cifs_sb->tcon, tmp_inode);
 		attr = le16_to_cpu(pfindData->Attributes);
 		allocation_size = le32_to_cpu(pfindData->AllocationSize);
 		end_of_file = le32_to_cpu(pfindData->DataSize);
-		tmp_inode->i_atime = CURRENT_TIME;
-		/* tmp_inode->i_mtime =  BB FIXME - add dos time handling
-		tmp_inode->i_ctime = 0;   BB FIXME */
-
 	}
 
 	/* Linux can not store file creation time unfortunately so ignore it */
@@ -938,6 +956,7 @@
 		filename = &pFindData->FileName[0];
 		/* one byte length, no name conversion */
 		len = (unsigned int)pFindData->FileNameLength;
+		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
 	} else {
 		cFYI(1,("Unknown findfirst level %d",level));
 		return -EINVAL;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 22b4c35..a8a0835 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -268,6 +268,10 @@
 	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
 	if(ses->serverOS)
 		strncpy(ses->serverOS, bcc_ptr, len);
+	if(strncmp(ses->serverOS, "OS/2",4) == 0) {
+			cFYI(1,("OS/2 server"));
+			ses->flags |= CIFS_SES_OS2;
+	}
 
 	bcc_ptr += len + 1;
 	bleft -= len + 1;
@@ -290,16 +294,11 @@
         if(len > bleft)
                 return rc;
 
-        if(ses->serverDomain)
-                kfree(ses->serverDomain);
-
-        ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
-        if(ses->serverOS)
-                strncpy(ses->serverOS, bcc_ptr, len);
-
-        bcc_ptr += len + 1;
-	bleft -= len + 1;
-
+	/* No domain field in LANMAN case. Domain is
+	   returned by old servers in the SMB negprot response */
+	/* BB For newer servers which do not support Unicode,
+	   but thus do return domain here we could add parsing
+	   for it later, but it is not very important */
 	cFYI(1,("ascii: bytes left %d",bleft));
 
 	return rc;
@@ -366,6 +365,8 @@
 	str_area = kmalloc(2000, GFP_KERNEL);
 	bcc_ptr = str_area;
 
+	ses->flags &= ~CIFS_SES_LANMAN;
+
 	if(type == LANMAN) {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		char lnm_session_key[CIFS_SESS_KEY_SIZE];
@@ -377,7 +378,7 @@
 		/* and copy into bcc */
 
 		calc_lanman_hash(ses, lnm_session_key);
-
+		ses->flags |= CIFS_SES_LANMAN; 
 /* #ifdef CONFIG_CIFS_DEBUG2
 		cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
 			CIFS_SESS_KEY_SIZE);
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index efaa044..7a1b2b9 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -364,20 +364,20 @@
 	smbhash(p24 + 16, c8, p21 + 14, 1);
 }
 
-void
+#if 0 /* currently unsued */
+static void
 D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
 {
 	smbhash(out, in, p14, 0);
 	smbhash(out + 8, in + 8, p14 + 7, 0);
 }
 
-void
+static void
 E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
 {
 	smbhash(out, in, p14, 1);
 	smbhash(out + 8, in + 8, p14 + 7, 1);
 }
-#if 0
 /* these routines are currently unneeded, but may be
 	needed later */
 void
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index f518c5e..4b25ba9 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -51,11 +51,8 @@
 
 void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
 void E_md4hash(const unsigned char *passwd, unsigned char *p16);
-void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
 static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
 		   unsigned char p24[24]);
-void NTLMSSPOWFencrypt(unsigned char passwd[8],
-		       unsigned char *ntlmchalresp, unsigned char p24[24]);
 void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
 
 /*
@@ -144,8 +141,9 @@
 	memset(wpwd,0,129 * 2);
 }
 
+#if 0 /* currently unused */
 /* Does both the NT and LM owfs of a user's password */
-void
+static void
 nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
 {
 	char passwd[514];
@@ -171,6 +169,7 @@
 	/* clear out local copy of user's password (just being paranoid). */
 	memset(passwd, '\0', sizeof (passwd));
 }
+#endif
 
 /* Does the NTLMv2 owfs of a user's password */
 #if 0  /* function not needed yet - but will be soon */
@@ -223,7 +222,8 @@
 }
 
 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
-void
+#if 0 /* currently unused */
+static void
 NTLMSSPOWFencrypt(unsigned char passwd[8],
 		  unsigned char *ntlmchalresp, unsigned char p24[24])
 {
@@ -235,6 +235,7 @@
 
 	E_P24(p21, ntlmchalresp, p24);
 }
+#endif
 
 /* Does the NT MD4 hash then des encryption. */
 
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 6dc6721..89e8da1 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -150,11 +150,6 @@
 	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
 	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
 
-	if (!ioprio_valid(aprio))
-		return bprio;
-	if (!ioprio_valid(bprio))
-		return aprio;
-
 	if (aclass == IOPRIO_CLASS_NONE)
 		aclass = IOPRIO_CLASS_BE;
 	if (bclass == IOPRIO_CLASS_NONE)
diff --git a/fs/splice.c b/fs/splice.c
index 13e92dd..a567010 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -607,7 +607,7 @@
 			ret = -ENOMEM;
 			page = page_cache_alloc_cold(mapping);
 			if (unlikely(!page))
-				goto out_nomem;
+				goto out_ret;
 
 			/*
 			 * This will also lock the page
@@ -666,7 +666,7 @@
 		if (sd->pos + this_len > isize)
 			vmtruncate(mapping->host, isize);
 
-		goto out;
+		goto out_ret;
 	}
 
 	if (buf->page != page) {
@@ -698,7 +698,7 @@
 out:
 	page_cache_release(page);
 	unlock_page(page);
-out_nomem:
+out_ret:
 	return ret;
 }
 
diff --git a/include/asm-i386/vic.h b/include/asm-i386/vic.h
index 4abfcfb..53100f3 100644
--- a/include/asm-i386/vic.h
+++ b/include/asm-i386/vic.h
@@ -58,4 +58,4 @@
 
 #define VIC_BOOT_INTERRUPT_MASK		0xfe
 
-extern void smp_vic_timer_interrupt(struct pt_regs *regs);
+extern void smp_vic_timer_interrupt(void);
diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h
index e74c54aa..5b27838 100644
--- a/include/asm-i386/voyager.h
+++ b/include/asm-i386/voyager.h
@@ -118,33 +118,33 @@
 } voyager_module_t;
 
 typedef struct voyager_eeprom_hdr {
-	 __u8  module_id[4] __attribute__((packed)); 
-	 __u8  version_id __attribute__((packed));
-	 __u8  config_id __attribute__((packed)); 
-	 __u16 boundry_id __attribute__((packed));	/* boundary scan id */
-	 __u16 ee_size __attribute__((packed));		/* size of EEPROM */
-	 __u8  assembly[11] __attribute__((packed));	/* assembly # */
-	 __u8  assembly_rev __attribute__((packed));	/* assembly rev */
-	 __u8  tracer[4] __attribute__((packed));	/* tracer number */
-	 __u16 assembly_cksum __attribute__((packed));	/* asm checksum */
-	 __u16 power_consump __attribute__((packed));	/* pwr requirements */
-	 __u16 num_asics __attribute__((packed));	/* number of asics */
-	 __u16 bist_time __attribute__((packed));	/* min. bist time */
-	 __u16 err_log_offset __attribute__((packed));	/* error log offset */
-	 __u16 scan_path_offset __attribute__((packed));/* scan path offset */
-	 __u16 cct_offset __attribute__((packed));
-	 __u16 log_length __attribute__((packed));	/* length of err log */
-	 __u16 xsum_end __attribute__((packed));	/* offset to end of
+	 __u8  module_id[4];
+	 __u8  version_id;
+	 __u8  config_id;
+	 __u16 boundry_id;	/* boundary scan id */
+	 __u16 ee_size;		/* size of EEPROM */
+	 __u8  assembly[11];	/* assembly # */
+	 __u8  assembly_rev;	/* assembly rev */
+	 __u8  tracer[4];	/* tracer number */
+	 __u16 assembly_cksum;	/* asm checksum */
+	 __u16 power_consump;	/* pwr requirements */
+	 __u16 num_asics;	/* number of asics */
+	 __u16 bist_time;	/* min. bist time */
+	 __u16 err_log_offset;	/* error log offset */
+	 __u16 scan_path_offset;/* scan path offset */
+	 __u16 cct_offset;
+	 __u16 log_length;	/* length of err log */
+	 __u16 xsum_end;	/* offset to end of
 							   checksum */
-	 __u8  reserved[4] __attribute__((packed));
-	 __u8  sflag __attribute__((packed));		/* starting sentinal */
-	 __u8  part_number[13] __attribute__((packed));	/* prom part number */
-	 __u8  version[10] __attribute__((packed));	/* version number */
-	 __u8  signature[8] __attribute__((packed));
-	 __u16 eeprom_chksum __attribute__((packed));
-	 __u32  data_stamp_offset __attribute__((packed));
-	 __u8  eflag  __attribute__((packed));		 /* ending sentinal */
-} voyager_eprom_hdr_t;
+	 __u8  reserved[4];
+	 __u8  sflag;		/* starting sentinal */
+	 __u8  part_number[13];	/* prom part number */
+	 __u8  version[10];	/* version number */
+	 __u8  signature[8];
+	 __u16 eeprom_chksum;
+	 __u32  data_stamp_offset;
+	 __u8  eflag ;		 /* ending sentinal */
+} __attribute__((packed)) voyager_eprom_hdr_t;
 
 
 
@@ -155,30 +155,30 @@
  * in the module EPROMs.  We really only care about the IDs and
  * offsets */
 typedef struct voyager_sp_table {
-	__u8 asic_id __attribute__((packed));
-	__u8 bypass_flag __attribute__((packed));
-	__u16 asic_data_offset __attribute__((packed));
-	__u16 config_data_offset __attribute__((packed));
-} voyager_sp_table_t;
+	__u8 asic_id;
+	__u8 bypass_flag;
+	__u16 asic_data_offset;
+	__u16 config_data_offset;
+} __attribute__((packed)) voyager_sp_table_t;
 
 typedef struct voyager_jtag_table {
-	__u8 icode[4] __attribute__((packed));
-	__u8 runbist[4] __attribute__((packed));
-	__u8 intest[4] __attribute__((packed));
-	__u8 samp_preld[4] __attribute__((packed));
-	__u8 ireg_len __attribute__((packed));
-} voyager_jtt_t;
+	__u8 icode[4];
+	__u8 runbist[4];
+	__u8 intest[4];
+	__u8 samp_preld[4];
+	__u8 ireg_len;
+} __attribute__((packed)) voyager_jtt_t;
 
 typedef struct voyager_asic_data_table {
-	__u8 jtag_id[4] __attribute__((packed));
-	__u16 length_bsr __attribute__((packed));
-	__u16 length_bist_reg __attribute__((packed));
-	__u32 bist_clk __attribute__((packed));
-	__u16 subaddr_bits __attribute__((packed));
-	__u16 seed_bits __attribute__((packed));
-	__u16 sig_bits __attribute__((packed));
-	__u16 jtag_offset __attribute__((packed));
-} voyager_at_t;
+	__u8 jtag_id[4];
+	__u16 length_bsr;
+	__u16 length_bist_reg;
+	__u32 bist_clk;
+	__u16 subaddr_bits;
+	__u16 seed_bits;
+	__u16 sig_bits;
+	__u16 jtag_offset;
+} __attribute__((packed)) voyager_at_t;
 
 /* Voyager Interrupt Controller (VIC) registers */
 
@@ -328,52 +328,52 @@
 #define NUMBER_OF_POS_REGS	8
 
 typedef struct {
-	__u8	MC_Slot __attribute__((packed));
-	__u8	POS_Values[NUMBER_OF_POS_REGS] __attribute__((packed));
-} MC_SlotInformation_t;
+	__u8	MC_Slot;
+	__u8	POS_Values[NUMBER_OF_POS_REGS];
+} __attribute__((packed)) MC_SlotInformation_t;
 
 struct QuadDescription {
-	__u8  Type __attribute__((packed));	/* for type 0 (DYADIC or MONADIC) all fields
+	__u8  Type;	/* for type 0 (DYADIC or MONADIC) all fields
                          * will be zero except for slot */
-	__u8 StructureVersion __attribute__((packed));
-	__u32 CPI_BaseAddress __attribute__((packed));
-	__u32  LARC_BankSize __attribute__((packed));	
-	__u32 LocalMemoryStateBits __attribute__((packed));
-	__u8  Slot __attribute__((packed)); /* Processor slots 1 - 4 */
-}; 
+	__u8 StructureVersion;
+	__u32 CPI_BaseAddress;
+	__u32  LARC_BankSize;
+	__u32 LocalMemoryStateBits;
+	__u8  Slot; /* Processor slots 1 - 4 */
+} __attribute__((packed));
 
 struct ProcBoardInfo { 
-	__u8 Type __attribute__((packed));    
-	__u8 StructureVersion __attribute__((packed));
-	__u8 NumberOfBoards __attribute__((packed));
-	struct QuadDescription QuadData[MAX_PROCESSOR_BOARDS] __attribute__((packed));
-};
+	__u8 Type;
+	__u8 StructureVersion;
+	__u8 NumberOfBoards;
+	struct QuadDescription QuadData[MAX_PROCESSOR_BOARDS];
+} __attribute__((packed));
 
 struct CacheDescription {
-	__u8 Level __attribute__((packed));
-	__u32 TotalSize __attribute__((packed));
-	__u16 LineSize __attribute__((packed));
-	__u8  Associativity __attribute__((packed));
-	__u8  CacheType __attribute__((packed));
-	__u8  WriteType __attribute__((packed));
-	__u8  Number_CPUs_SharedBy __attribute__((packed));
-	__u8  Shared_CPUs_Hardware_IDs[MAX_SHARED_CPUS] __attribute__((packed));
+	__u8 Level;
+	__u32 TotalSize;
+	__u16 LineSize;
+	__u8  Associativity;
+	__u8  CacheType;
+	__u8  WriteType;
+	__u8  Number_CPUs_SharedBy;
+	__u8  Shared_CPUs_Hardware_IDs[MAX_SHARED_CPUS];
 
-};
+} __attribute__((packed));
 
 struct CPU_Description {
-	__u8 CPU_HardwareId __attribute__((packed));
-	char *FRU_String __attribute__((packed));
-	__u8 NumberOfCacheLevels __attribute__((packed));
-	struct CacheDescription CacheLevelData[MAX_CACHE_LEVELS] __attribute__((packed));
-};
+	__u8 CPU_HardwareId;
+	char *FRU_String;
+	__u8 NumberOfCacheLevels;
+	struct CacheDescription CacheLevelData[MAX_CACHE_LEVELS];
+} __attribute__((packed));
 
 struct CPU_Info {
-	__u8 Type __attribute__((packed));
-	__u8 StructureVersion __attribute__((packed));
-	__u8 NumberOf_CPUs __attribute__((packed));
-	struct CPU_Description CPU_Data[MAX_CPUS] __attribute__((packed));
-};
+	__u8 Type;
+	__u8 StructureVersion;
+	__u8 NumberOf_CPUs;
+	struct CPU_Description CPU_Data[MAX_CPUS];
+} __attribute__((packed));
 
 
 /*
diff --git a/include/asm-sh/cpu-sh4/ubc.h b/include/asm-sh/cpu-sh4/ubc.h
index 3d09431..c86e170 100644
--- a/include/asm-sh/cpu-sh4/ubc.h
+++ b/include/asm-sh/cpu-sh4/ubc.h
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1999 Niibe Yutaka
  * Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -11,6 +12,41 @@
 #ifndef __ASM_CPU_SH4_UBC_H
 #define __ASM_CPU_SH4_UBC_H
 
+#if defined(CONFIG_CPU_SH4A)
+#define UBC_CBR0		0xff200000
+#define UBC_CRR0		0xff200004
+#define UBC_CAR0		0xff200008
+#define UBC_CAMR0		0xff20000c
+#define UBC_CBR1		0xff200020
+#define UBC_CRR1		0xff200024
+#define UBC_CAR1		0xff200028
+#define UBC_CAMR1		0xff20002c
+#define UBC_CDR1		0xff200030
+#define UBC_CDMR1		0xff200034
+#define UBC_CETR1		0xff200038
+#define UBC_CCMFR		0xff200600
+#define UBC_CBCR		0xff200620
+
+/* CBR	*/
+#define UBC_CBR_AIE		(0x01<<30)
+#define UBC_CBR_ID_INST		(0x01<<4)
+#define UBC_CBR_RW_READ		(0x01<<1)
+#define UBC_CBR_CE		(0x01)
+
+#define	UBC_CBR_AIV_MASK	(0x00FF0000)
+#define	UBC_CBR_AIV_SHIFT	(16)
+#define UBC_CBR_AIV_SET(asid)	(((asid)<<UBC_CBR_AIV_SHIFT) & UBC_CBR_AIV_MASK)
+
+#define UBC_CBR_INIT		0x20000000
+
+/* CRR	*/
+#define UBC_CRR_RES		(0x01<<13)
+#define UBC_CRR_PCB		(0x01<<1)
+#define UBC_CRR_BIE		(0x01)
+
+#define UBC_CRR_INIT		0x00002000
+
+#else	/* CONFIG_CPU_SH4 */
 #define UBC_BARA		0xff200000
 #define UBC_BAMRA		0xff200004
 #define UBC_BBRA		0xff200008
@@ -22,6 +58,7 @@
 #define UBC_BDRB		0xff200018
 #define UBC_BDMRB		0xff20001c
 #define UBC_BRCR		0xff200020
+#endif	/* CONFIG_CPU_SH4 */
 
 #endif /* __ASM_CPU_SH4_UBC_H */
 
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index fed2661..80ee1cd 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -1,4 +1,8 @@
 #ifndef __ASM_SH_HW_IRQ_H
 #define __ASM_SH_HW_IRQ_H
 
+#include <asm/atomic.h>
+
+extern atomic_t irq_err_count;
+
 #endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 0e5f365..28996f9 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -697,13 +697,15 @@
 
 #define INTC2_INTPRI_OFFSET	0x00
 
-void make_intc2_irq(unsigned int irq,
-		    unsigned int ipr_offset, unsigned int ipr_shift,
-		    unsigned int msk_offset, unsigned int msk_shift,
-		    unsigned int priority);
-void init_IRQ_intc2(void);
-void intc2_add_clear_irq(int irq, int (*fn)(int));
+struct intc2_data {
+	unsigned short irq;
+	unsigned char ipr_offset, ipr_shift;
+	unsigned char msk_offset, msk_shift;
+	unsigned char priority;
+};
 
+void make_intc2_irq(struct intc2_data *);
+void init_IRQ_intc2(void);
 #endif
 
 extern int shmse_irq_demux(int irq);
diff --git a/include/asm-sh/irq_regs.h b/include/asm-sh/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/include/asm-sh/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h
index c7ab280..5df842b 100644
--- a/include/asm-sh/timer.h
+++ b/include/asm-sh/timer.h
@@ -8,8 +8,9 @@
 	int (*init)(void);
 	int (*start)(void);
 	int (*stop)(void);
+#ifndef CONFIG_GENERIC_TIME
 	unsigned long (*get_offset)(void);
-	unsigned long (*get_frequency)(void);
+#endif
 };
 
 struct sys_timer {
@@ -24,21 +25,17 @@
 extern struct sys_timer tmu_timer;
 extern struct sys_timer *sys_timer;
 
+#ifndef CONFIG_GENERIC_TIME
 static inline unsigned long get_timer_offset(void)
 {
 	return sys_timer->ops->get_offset();
 }
-
-static inline unsigned long get_timer_frequency(void)
-{
-	return sys_timer->ops->get_frequency();
-}
+#endif
 
 /* arch/sh/kernel/timers/timer.c */
 struct sys_timer *get_sys_timer(void);
 
 /* arch/sh/kernel/time.c */
-void handle_timer_tick(struct pt_regs *);
+void handle_timer_tick(void);
 
 #endif /* __ASM_SH_TIMER_H */
-
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 26f7856..d370d2c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -157,6 +157,7 @@
 	REQ_TYPE_ATA_CMD,
 	REQ_TYPE_ATA_TASK,
 	REQ_TYPE_ATA_TASKFILE,
+	REQ_TYPE_ATA_PC,
 };
 
 /*
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index b3370ef..2fa9f11 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -70,7 +70,6 @@
 {
 	struct list_head list;
 	struct elevator_ops ops;
-	struct elevator_type *elevator_type;
 	struct elv_fs_entry *elevator_attrs;
 	char elevator_name[ELV_NAME_MAX];
 	struct module *elevator_owner;
diff --git a/include/linux/security.h b/include/linux/security.h
index 9b5fea8..b200b98 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -882,7 +882,8 @@
  *	Check permission when a flow selects a xfrm_policy for processing
  *	XFRMs on a packet.  The hook is called when selecting either a
  *	per-socket policy or a generic xfrm policy.
- *	Return 0 if permission is granted.
+ *	Return 0 if permission is granted, -ESRCH otherwise, or -errno
+ *	on other errors.
  * @xfrm_state_pol_flow_match:
  *	@x contains the state to match.
  *	@xp contains the policy to check for a match.
@@ -891,6 +892,7 @@
  * @xfrm_flow_state_match:
  *	@fl contains the flow key to match.
  *	@xfrm points to the xfrm_state to match.
+ *	@xp points to the xfrm_policy to match.
  *	Return 1 if there is a match.
  * @xfrm_decode_session:
  *	@skb points to skb to decode.
@@ -1388,7 +1390,8 @@
 	int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
 	int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
 			struct xfrm_policy *xp, struct flowi *fl);
-	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
+	int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm,
+			struct xfrm_policy *xp);
 	int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
@@ -3120,11 +3123,6 @@
 	return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
 }
 
-static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
-{
-	return security_ops->xfrm_policy_alloc_security(xp, NULL, sk);
-}
-
 static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
 {
 	return security_ops->xfrm_policy_clone_security(old, new);
@@ -3175,9 +3173,10 @@
 	return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
 }
 
-static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+static inline int security_xfrm_flow_state_match(struct flowi *fl,
+			struct xfrm_state *xfrm, struct xfrm_policy *xp)
 {
-	return security_ops->xfrm_flow_state_match(fl, xfrm);
+	return security_ops->xfrm_flow_state_match(fl, xfrm, xp);
 }
 
 static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
@@ -3197,11 +3196,6 @@
 	return 0;
 }
 
-static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk)
-{
-	return 0;
-}
-
 static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
 {
 	return 0;
@@ -3249,7 +3243,7 @@
 }
 
 static inline int security_xfrm_flow_state_match(struct flowi *fl,
-                                struct xfrm_state *xfrm)
+			struct xfrm_state *xfrm, struct xfrm_policy *xp)
 {
 	return 1;
 }
diff --git a/include/net/flow.h b/include/net/flow.h
index ddf5f3c..3b44d72 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -97,7 +97,7 @@
 #define FLOW_DIR_FWD	2
 
 struct sock;
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+typedef int (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp);
 
 extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 6d14c22..5f48748 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -196,6 +196,7 @@
 {
 	if (atomic_dec_and_test(&tw->tw_refcnt)) {
 		struct module *owner = tw->tw_prot->owner;
+		twsk_destructor((struct sock *)tw);
 #ifdef SOCK_REFCNT_DEBUG
 		printk(KERN_DEBUG "%s timewait_sock %p released\n",
 		       tw->tw_prot->name, tw);
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index c63a580..113337c 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -34,6 +34,7 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <net/netlink.h>
+#include <asm/atomic.h>
 
 /*
  * NetLabel - A management interface for maintaining network packet label
@@ -106,6 +107,7 @@
 
 /* LSM security attributes */
 struct netlbl_lsm_cache {
+	atomic_t refcount;
 	void (*free) (const void *data);
 	void *data;
 };
@@ -117,7 +119,7 @@
 	unsigned char *mls_cat;
 	size_t mls_cat_len;
 
-	struct netlbl_lsm_cache cache;
+	struct netlbl_lsm_cache *cache;
 };
 
 /*
@@ -126,6 +128,43 @@
 
 
 /**
+ * netlbl_secattr_cache_alloc - Allocate and initialize a secattr cache
+ * @flags: the memory allocation flags
+ *
+ * Description:
+ * Allocate and initialize a netlbl_lsm_cache structure.  Returns a pointer
+ * on success, NULL on failure.
+ *
+ */
+static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(int flags)
+{
+	struct netlbl_lsm_cache *cache;
+
+	cache = kzalloc(sizeof(*cache), flags);
+	if (cache)
+		atomic_set(&cache->refcount, 1);
+	return cache;
+}
+
+/**
+ * netlbl_secattr_cache_free - Frees a netlbl_lsm_cache struct
+ * @cache: the struct to free
+ *
+ * Description:
+ * Frees @secattr including all of the internal buffers.
+ *
+ */
+static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
+{
+	if (!atomic_dec_and_test(&cache->refcount))
+		return;
+
+	if (cache->free)
+		cache->free(cache->data);
+	kfree(cache);
+}
+
+/**
  * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
  * @secattr: the struct to initialize
  *
@@ -143,20 +182,16 @@
 /**
  * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct
  * @secattr: the struct to clear
- * @clear_cache: cache clear flag
  *
  * Description:
  * Destroys the @secattr struct, including freeing all of the internal buffers.
- * If @clear_cache is true then free the cache fields, otherwise leave them
- * intact.  The struct must be reset with a call to netlbl_secattr_init()
- * before reuse.
+ * The struct must be reset with a call to netlbl_secattr_init() before reuse.
  *
  */
-static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr,
-					  u32 clear_cache)
+static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
 {
-	if (clear_cache && secattr->cache.data != NULL && secattr->cache.free)
-		secattr->cache.free(secattr->cache.data);
+	if (secattr->cache)
+		netlbl_secattr_cache_free(secattr->cache);
 	kfree(secattr->domain);
 	kfree(secattr->mls_cat);
 }
@@ -178,17 +213,14 @@
 /**
  * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct
  * @secattr: the struct to free
- * @clear_cache: cache clear flag
  *
  * Description:
- * Frees @secattr including all of the internal buffers.  If @clear_cache is
- * true then free the cache fields, otherwise leave them intact.
+ * Frees @secattr including all of the internal buffers.
  *
  */
-static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr,
-				       u32 clear_cache)
+static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
 {
-	netlbl_secattr_destroy(secattr, clear_cache);
+	netlbl_secattr_destroy(secattr);
 	kfree(secattr);
 }
 
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ee68a31..764e3af 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -139,6 +139,7 @@
 void sctp_write_space(struct sock *sk);
 unsigned int sctp_poll(struct file *file, struct socket *sock,
 		poll_table *wait);
+void sctp_sock_rfree(struct sk_buff *skb);
 
 /*
  * sctp/primitive.c
@@ -444,6 +445,19 @@
 	return result;
 }
 
+/* SCTP version of skb_set_owner_r.  We need this one because
+ * of the way we have to do receive buffer accounting on bundled
+ * chunks.
+ */
+static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+	struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+	skb->sk = sk;
+	skb->destructor = sctp_sock_rfree;
+	atomic_add(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
 /* Tests if the list has one and only one entry. */
 static inline int sctp_list_single_entry(struct list_head *head)
 {
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 6c40cfc..1a4ddc1 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -63,6 +63,7 @@
 	__u32 cumtsn;
 	int msg_flags;
 	int iif;
+	unsigned int rmem_len;
 };
 
 /* Retrieve the skb this event sits inside of. */
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
index 2544281..be293d7 100644
--- a/include/net/timewait_sock.h
+++ b/include/net/timewait_sock.h
@@ -19,6 +19,7 @@
 	unsigned int	twsk_obj_size;
 	int		(*twsk_unique)(struct sock *sk,
 				       struct sock *sktw, void *twp);
+	void		(*twsk_destructor)(struct sock *sk);
 };
 
 static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -28,4 +29,10 @@
 	return 0;
 }
 
+static inline void twsk_destructor(struct sock *sk)
+{
+	if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
+		sk->sk_prot->twsk_prot->twsk_destructor(sk);
+}
+
 #endif /* _TIMEWAIT_SOCK_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1e2a4dd..737fdb2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -995,7 +995,8 @@
 				  int create, unsigned short family);
 extern void xfrm_policy_flush(u8 type);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
-extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict);
+extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
+			  struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 
 extern wait_queue_head_t km_waitq;
diff --git a/net/compat.c b/net/compat.c
index d5d69fa..52d32f1 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -285,8 +285,7 @@
 
 	if (i > 0) {
 		int cmlen = CMSG_COMPAT_LEN(i * sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		err = put_user(SOL_SOCKET, &cm->cmsg_level);
 		if (!err)
 			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
 		if (!err)
diff --git a/net/core/flow.c b/net/core/flow.c
index f23e7e3..b16d31a 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -85,6 +85,14 @@
 	add_timer(&flow_hash_rnd_timer);
 }
 
+static void flow_entry_kill(int cpu, struct flow_cache_entry *fle)
+{
+	if (fle->object)
+		atomic_dec(fle->object_ref);
+	kmem_cache_free(flow_cachep, fle);
+	flow_count(cpu)--;
+}
+
 static void __flow_cache_shrink(int cpu, int shrink_to)
 {
 	struct flow_cache_entry *fle, **flp;
@@ -100,10 +108,7 @@
 		}
 		while ((fle = *flp) != NULL) {
 			*flp = fle->next;
-			if (fle->object)
-				atomic_dec(fle->object_ref);
-			kmem_cache_free(flow_cachep, fle);
-			flow_count(cpu)--;
+			flow_entry_kill(cpu, fle);
 		}
 	}
 }
@@ -220,24 +225,33 @@
 
 nocache:
 	{
+		int err;
 		void *obj;
 		atomic_t *obj_ref;
 
-		resolver(key, family, dir, &obj, &obj_ref);
+		err = resolver(key, family, dir, &obj, &obj_ref);
 
 		if (fle) {
-			fle->genid = atomic_read(&flow_cache_genid);
+			if (err) {
+				/* Force security policy check on next lookup */
+				*head = fle->next;
+				flow_entry_kill(cpu, fle);
+			} else {
+				fle->genid = atomic_read(&flow_cache_genid);
 
-			if (fle->object)
-				atomic_dec(fle->object_ref);
+				if (fle->object)
+					atomic_dec(fle->object_ref);
 
-			fle->object = obj;
-			fle->object_ref = obj_ref;
-			if (obj)
-				atomic_inc(fle->object_ref);
+				fle->object = obj;
+				fle->object_ref = obj_ref;
+				if (obj)
+					atomic_inc(fle->object_ref);
+			}
 		}
 		local_bh_enable();
 
+		if (err)
+			obj = ERR_PTR(err);
 		return obj;
 	}
 }
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 221e403..02f3c79 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -602,7 +602,7 @@
 		goto errout;
 	}
 
-	err = rtnl_unicast(skb, NETLINK_CB(skb).pid);
+	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
 	kfree(iw_buf);
 	dev_put(dev);
diff --git a/net/core/scm.c b/net/core/scm.c
index 649d01e..271cf06 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -245,8 +245,7 @@
 	if (i > 0)
 	{
 		int cmlen = CMSG_LEN(i*sizeof(int));
-		if (!err)
-			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		err = put_user(SOL_SOCKET, &cm->cmsg_level);
 		if (!err)
 			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
 		if (!err)
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index bf692c1..7e746c4 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -311,7 +311,7 @@
 	}
 
 	if (sk->sk_state == DCCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -614,7 +614,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -980,7 +980,7 @@
 	goto discard_it;
 
 do_time_wait:
-	inet_twsk_put((struct inet_timewait_sock *)sk);
+	inet_twsk_put(inet_twsk(sk));
 	goto no_dccp_socket;
 }
 
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 7a47399..7171a78 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -285,7 +285,7 @@
 	}
 
 	if (sk->sk_state == DCCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -663,7 +663,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -1109,7 +1109,7 @@
 	goto discard_it;
 
 do_time_wait:
-	inet_twsk_put((struct inet_timewait_sock *)sk);
+	inet_twsk_put(inet_twsk(sk));
 	goto no_dccp_socket;
 }
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 70e0273..3456cd3 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -1178,8 +1178,10 @@
 	if (peer) {
 		if ((sock->state != SS_CONNECTED && 
 		     sock->state != SS_CONNECTING) && 
-		    scp->accept_mode == ACC_IMMED)
+		    scp->accept_mode == ACC_IMMED) {
+		    	release_sock(sk);
 			return -ENOTCONN;
+		}
 
 		memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));
 	} else {
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index dd0761e..a2a43d8 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -267,9 +267,14 @@
 
 static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 {
-	return memcmp(&fl1->nl_u.dn_u, &fl2->nl_u.dn_u, sizeof(fl1->nl_u.dn_u)) == 0 &&
-		fl1->oif == fl2->oif &&
-		fl1->iif == fl2->iif;
+	return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
+		(fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
+#ifdef CONFIG_IP_ROUTE_FWMARK
+		(fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
+#endif
+		(fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
+		(fl1->oif ^ fl2->oif) |
+		(fl1->iif ^ fl2->iif)) == 0;
 }
 
 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a8e2e87..bde8cca 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -43,6 +43,7 @@
 #include <net/tcp.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
+#include <asm/atomic.h>
 #include <asm/bug.h>
 
 struct cipso_v4_domhsh_entry {
@@ -79,7 +80,7 @@
 	unsigned char *key;
 	size_t key_len;
 
-	struct netlbl_lsm_cache lsm_data;
+	struct netlbl_lsm_cache *lsm_data;
 
 	u32 activity;
 	struct list_head list;
@@ -188,13 +189,14 @@
  * @entry: the entry to free
  *
  * Description:
- * This function frees the memory associated with a cache entry.
+ * This function frees the memory associated with a cache entry including the
+ * LSM cache data if there are no longer any users, i.e. reference count == 0.
  *
  */
 static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
 {
-	if (entry->lsm_data.free)
-		entry->lsm_data.free(entry->lsm_data.data);
+	if (entry->lsm_data)
+		netlbl_secattr_cache_free(entry->lsm_data);
 	kfree(entry->key);
 	kfree(entry);
 }
@@ -315,8 +317,8 @@
 		    entry->key_len == key_len &&
 		    memcmp(entry->key, key, key_len) == 0) {
 			entry->activity += 1;
-			secattr->cache.free = entry->lsm_data.free;
-			secattr->cache.data = entry->lsm_data.data;
+			atomic_inc(&entry->lsm_data->refcount);
+			secattr->cache = entry->lsm_data;
 			if (prev_entry == NULL) {
 				spin_unlock_bh(&cipso_v4_cache[bkt].lock);
 				return 0;
@@ -383,8 +385,8 @@
 	memcpy(entry->key, cipso_ptr, cipso_ptr_len);
 	entry->key_len = cipso_ptr_len;
 	entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
-	entry->lsm_data.free = secattr->cache.free;
-	entry->lsm_data.data = secattr->cache.data;
+	atomic_inc(&secattr->cache->refcount);
+	entry->lsm_data = secattr->cache;
 
 	bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
 	spin_lock_bh(&cipso_v4_cache[bkt].lock);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f5fba05..d5b5dec 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -611,8 +611,8 @@
 		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
 		 */
 		if (flags == 0 &&
-		    skb->protocol == __constant_htons(ETH_P_WCCP)) {
-			skb->protocol = __constant_htons(ETH_P_IP);
+		    skb->protocol == htons(ETH_P_WCCP)) {
+			skb->protocol = htons(ETH_P_IP);
 			if ((*(h + offset) & 0xF0) != 0x40) 
 				offset += 4;
 		}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index c41ddba..925ee4d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -566,9 +566,15 @@
 
 static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
 {
-	return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 &&
-	       fl1->oif     == fl2->oif &&
-	       fl1->iif     == fl2->iif;
+	return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
+		(fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) |
+#ifdef CONFIG_IP_ROUTE_FWMARK
+		(fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
+#endif
+		(*(u16 *)&fl1->nl_u.ip4_u.tos ^
+		 *(u16 *)&fl2->nl_u.ip4_u.tos) |
+		(fl1->oif ^ fl2->oif) |
+		(fl1->iif ^ fl2->iif)) == 0;
 }
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c83938b..6bbd985 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -355,7 +355,7 @@
 		return;
 	}
 	if (sk->sk_state == TCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -578,7 +578,7 @@
 	struct tcphdr *th = skb->h.th;
 	struct {
 		struct tcphdr th;
-		u32 tsopt[3];
+		u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2];
 	} rep;
 	struct ip_reply_arg arg;
 
@@ -960,7 +960,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -1154,26 +1154,24 @@
 
 do_time_wait:
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-		inet_twsk_put((struct inet_timewait_sock *) sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
 	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TCP_MIB_INERRS);
-		inet_twsk_put((struct inet_timewait_sock *) sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
-	switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
-					   skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
 	case TCP_TW_SYN: {
 		struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
 							skb->nh.iph->daddr,
 							th->dest,
 							inet_iif(skb));
 		if (sk2) {
-			inet_twsk_deschedule((struct inet_timewait_sock *)sk,
-					     &tcp_death_row);
-			inet_twsk_put((struct inet_timewait_sock *)sk);
+			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
+			inet_twsk_put(inet_twsk(sk));
 			sk = sk2;
 			goto process;
 		}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9a253fa..f22536e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -273,10 +273,10 @@
 					 __u32 tstamp)
 {
 	if (tp->rx_opt.tstamp_ok) {
-		*ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
-					  (TCPOPT_NOP << 16) |
-					  (TCPOPT_TIMESTAMP << 8) |
-					  TCPOLEN_TIMESTAMP);
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_NOP << 16) |
+			       (TCPOPT_TIMESTAMP << 8) |
+			       TCPOLEN_TIMESTAMP);
 		*ptr++ = htonl(tstamp);
 		*ptr++ = htonl(tp->rx_opt.ts_recent);
 	}
@@ -325,18 +325,27 @@
 	*ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
 	if (ts) {
 		if(sack)
-			*ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
-						  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl((TCPOPT_SACK_PERM << 24) |
+				       (TCPOLEN_SACK_PERM << 16) |
+				       (TCPOPT_TIMESTAMP << 8) |
+				       TCPOLEN_TIMESTAMP);
 		else
-			*ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
-						  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl((TCPOPT_NOP << 24) |
+				       (TCPOPT_NOP << 16) |
+				       (TCPOPT_TIMESTAMP << 8) |
+				       TCPOLEN_TIMESTAMP);
 		*ptr++ = htonl(tstamp);		/* TSVAL */
 		*ptr++ = htonl(ts_recent);	/* TSECR */
 	} else if(sack)
-		*ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
-					  (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_NOP << 16) |
+			       (TCPOPT_SACK_PERM << 8) |
+			       TCPOLEN_SACK_PERM);
 	if (offer_wscale)
-		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+		*ptr++ = htonl((TCPOPT_NOP << 24) |
+			       (TCPOPT_WINDOW << 16) |
+			       (TCPOLEN_WINDOW << 8) |
+			       (wscale));
 }
 
 /* This routine actually transmits TCP packets queued in by
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7a7a001..1bed0cd 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -52,7 +52,7 @@
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
 	    	    xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
-		    xfrm_bundle_ok(xdst, fl, AF_INET, 0)) {
+		    xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
 			dst_clone(dst);
 			break;
 		}
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index a460e81..ef5eaad 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -153,6 +153,19 @@
 	---help---
 	  Support for MIPv6 route optimization mode.
 
+config IPV6_SIT
+	tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
+	depends on IPV6
+	default y
+	---help---
+	  Tunneling means encapsulating data of one protocol type within
+	  another protocol and sending it over a channel that understands the
+	  encapsulating protocol. This driver implements encapsulation of IPv6
+	  into IPv4 packets. This is useful if you want to connect two IPv6
+	  networks over an IPv4-only path.
+
+	  Saying M here will produce a module called sit.ko. If unsure, say Y.
+
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
 	select INET6_TUNNEL
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 87274e4..addcc01 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_IPV6) += ipv6.o
 
-ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
+ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
 		route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \
 		protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
 		exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
@@ -29,6 +29,7 @@
 obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
+obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 
 obj-y += exthdrs_core.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e03c33b..b312a5f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -396,8 +396,10 @@
 	ndev->regen_timer.data = (unsigned long) ndev;
 	if ((dev->flags&IFF_LOOPBACK) ||
 	    dev->type == ARPHRD_TUNNEL ||
-	    dev->type == ARPHRD_NONE ||
-	    dev->type == ARPHRD_SIT) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+	    dev->type == ARPHRD_SIT ||
+#endif
+	    dev->type == ARPHRD_NONE) {
 		printk(KERN_INFO
 		       "%s: Disabled Privacy Extensions\n",
 		       dev->name);
@@ -1546,8 +1548,10 @@
 	   This thing is done here expecting that the whole
 	   class of non-broadcast devices need not cloning.
 	 */
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 	if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
 		cfg.fc_flags |= RTF_NONEXTHOP;
+#endif
 
 	ip6_route_add(&cfg);
 }
@@ -1569,6 +1573,7 @@
 	ip6_route_add(&cfg);
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void sit_route_add(struct net_device *dev)
 {
 	struct fib6_config cfg = {
@@ -1582,6 +1587,7 @@
 	/* prefix length - 96 bits "::d.d.d.d" */
 	ip6_route_add(&cfg);
 }
+#endif
 
 static void addrconf_add_lroute(struct net_device *dev)
 {
@@ -1852,6 +1858,7 @@
 	if (dev == NULL)
 		goto err_exit;
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 	if (dev->type == ARPHRD_SIT) {
 		struct ifreq ifr;
 		mm_segment_t	oldfs;
@@ -1881,6 +1888,7 @@
 			err = dev_open(dev);
 		}
 	}
+#endif
 
 err_exit:
 	rtnl_unlock();
@@ -2010,6 +2018,7 @@
 	return err;
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void sit_add_v4_addrs(struct inet6_dev *idev)
 {
 	struct inet6_ifaddr * ifp;
@@ -2078,6 +2087,7 @@
 		}
         }
 }
+#endif
 
 static void init_loopback(struct net_device *dev)
 {
@@ -2141,6 +2151,7 @@
 		addrconf_add_linklocal(idev, &addr);
 }
 
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 static void addrconf_sit_config(struct net_device *dev)
 {
 	struct inet6_dev *idev;
@@ -2166,6 +2177,7 @@
 	} else
 		sit_route_add(dev);
 }
+#endif
 
 static inline int
 ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev)
@@ -2260,9 +2272,11 @@
 		}
 
 		switch(dev->type) {
+#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
 		case ARPHRD_SIT:
 			addrconf_sit_config(dev);
 			break;
+#endif
 		case ARPHRD_TUNNEL6:
 			addrconf_ip6_tnl_config(dev);
 			break;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e94eccb..858cae2 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -850,7 +850,6 @@
 	err = addrconf_init();
 	if (err)
 		goto addrconf_fail;
-	sit_init();
 
 	/* Init v6 extension headers. */
 	ipv6_rthdr_init();
@@ -927,7 +926,6 @@
 	mip6_fini();
 #endif
 	/* Cleanup code parts. */
-	sit_cleanup();
 	ip6_flowlabel_cleanup();
 	addrconf_cleanup();
 	ip6_route_cleanup();
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 836eecd..dc5765b 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -850,3 +850,6 @@
 	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
 	goto out;
 }
+
+module_init(sit_init);
+module_exit(sit_cleanup);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 3b65754..4c2a7c0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -329,7 +329,7 @@
 	}
 
 	if (sk->sk_state == TCP_TIME_WAIT) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		return;
 	}
 
@@ -653,7 +653,7 @@
 	int tot_len = sizeof(struct tcphdr);
 
 	if (ts)
-		tot_len += 3*4;
+		tot_len += TCPOLEN_TSTAMP_ALIGNED;
 
 	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
 			 GFP_ATOMIC);
@@ -749,7 +749,7 @@
 			bh_lock_sock(nsk);
 			return nsk;
 		}
-		inet_twsk_put((struct inet_timewait_sock *)nsk);
+		inet_twsk_put(inet_twsk(nsk));
 		return NULL;
 	}
 
@@ -1283,18 +1283,17 @@
 
 do_time_wait:
 	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TCP_MIB_INERRS);
-		inet_twsk_put((struct inet_timewait_sock *)sk);
+		inet_twsk_put(inet_twsk(sk));
 		goto discard_it;
 	}
 
-	switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
-					   skb, th)) {
+	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
 	case TCP_TW_SYN:
 	{
 		struct sock *sk2;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6a252e2..73cee2e 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -73,7 +73,7 @@
 				 xdst->u.rt6.rt6i_src.plen);
 		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
 		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
-		    xfrm_bundle_ok(xdst, fl, AF_INET6,
+		    xfrm_bundle_ok(policy, xdst, fl, AF_INET6,
 				   (xdst->u.rt6.rt6i_dst.plen != 128 ||
 				    xdst->u.rt6.rt6i_src.plen != 128))) {
 			dst_clone(dst);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ff98e70..20ff7cc 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2928,11 +2928,6 @@
 		if (*dir)
 			goto out;
 	}
-	else {
-		*dir = security_xfrm_sock_policy_alloc(xp, sk);
-		if (*dir)
-			goto out;
-	}
 
 	*dir = pol->sadb_x_policy_dir-1;
 	return xp;
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 54fb7de..ff97110 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -200,7 +200,7 @@
 int netlbl_cache_add(const struct sk_buff *skb,
 		     const struct netlbl_lsm_secattr *secattr)
 {
-	if (secattr->cache.data == NULL)
+	if (secattr->cache == NULL)
 		return -ENOMSG;
 
 	if (CIPSO_V4_OPTEXIST(skb))
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index bb3ddd4..9b9c555 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -786,11 +786,10 @@
 	for (i = 0; i < 500; i++) {
 		struct htb_class *cl;
 		long diff;
-		struct rb_node *p = q->wait_pq[level].rb_node;
+		struct rb_node *p = rb_first(&q->wait_pq[level]);
+
 		if (!p)
 			return 0;
-		while (p->rb_left)
-			p = p->rb_left;
 
 		cl = rb_entry(p, struct htb_class, pq_node);
 		if (time_after(cl->pq_key, q->jiffies)) {
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index a356d8d3..7f49e76 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -344,7 +344,7 @@
 			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
 			   assoc->state, hash, assoc->assoc_id,
 			   assoc->sndbuf_used,
-			   (sk->sk_rcvbuf - assoc->rwnd),
+			   atomic_read(&assoc->rmem_alloc),
 			   sock_i_uid(sk), sock_i_ino(sk),
 			   epb->bind_addr.port,
 			   assoc->peer.port);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 3fe906d..9deec43 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5362,6 +5362,20 @@
 	sctp_association_put(asoc);
 }
 
+/* Do accounting for the receive space on the socket.
+ * Accounting for the association is done in ulpevent.c
+ * We set this as a destructor for the cloned data skbs so that
+ * accounting is done at the correct time.
+ */
+void sctp_sock_rfree(struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+	struct sctp_ulpevent *event = sctp_skb2event(skb);
+
+	atomic_sub(event->rmem_len, &sk->sk_rmem_alloc);
+}
+
+
 /* Helper function to wait for space in the sndbuf.  */
 static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
 				size_t msg_len)
@@ -5634,10 +5648,10 @@
 	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
 		event = sctp_skb2event(skb);
 		if (event->asoc == assoc) {
-			sock_rfree(skb);
+			sctp_sock_rfree(skb);
 			__skb_unlink(skb, &oldsk->sk_receive_queue);
 			__skb_queue_tail(&newsk->sk_receive_queue, skb);
-			skb_set_owner_r(skb, newsk);
+			sctp_skb_set_owner_r(skb, newsk);
 		}
 	}
 
@@ -5665,10 +5679,10 @@
 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
 			event = sctp_skb2event(skb);
 			if (event->asoc == assoc) {
-				sock_rfree(skb);
+				sctp_sock_rfree(skb);
 				__skb_unlink(skb, &oldsp->pd_lobby);
 				__skb_queue_tail(queue, skb);
-				skb_set_owner_r(skb, newsk);
+				sctp_skb_set_owner_r(skb, newsk);
 			}
 		}
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index ee236784..a015283 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -55,10 +55,13 @@
 
 
 /* Initialize an ULP event from an given skb.  */
-SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
+SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event,
+				    int msg_flags,
+				    unsigned int len)
 {
 	memset(event, 0, sizeof(struct sctp_ulpevent));
 	event->msg_flags = msg_flags;
+	event->rmem_len = len;
 }
 
 /* Create a new sctp_ulpevent.  */
@@ -73,7 +76,7 @@
 		goto fail;
 
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, msg_flags);
+	sctp_ulpevent_init(event, msg_flags, skb->truesize);
 
 	return event;
 
@@ -101,17 +104,16 @@
 	sctp_association_hold((struct sctp_association *)asoc);
 	skb = sctp_event2skb(event);
 	event->asoc = (struct sctp_association *)asoc;
-	atomic_add(skb->truesize, &event->asoc->rmem_alloc);
-	skb_set_owner_r(skb, asoc->base.sk);
+	atomic_add(event->rmem_len, &event->asoc->rmem_alloc);
+	sctp_skb_set_owner_r(skb, asoc->base.sk);
 }
 
 /* A simple destructor to give up the reference to the association. */
 static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
 {
 	struct sctp_association *asoc = event->asoc;
-	struct sk_buff *skb = sctp_event2skb(event);
 
-	atomic_sub(skb->truesize, &asoc->rmem_alloc);
+	atomic_sub(event->rmem_len, &asoc->rmem_alloc);
 	sctp_association_put(asoc);
 }
 
@@ -372,7 +374,7 @@
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, MSG_NOTIFICATION);
+	sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
 
 	sre = (struct sctp_remote_error *)
 		skb_push(skb, sizeof(struct sctp_remote_error));
@@ -464,7 +466,7 @@
 
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
-	sctp_ulpevent_init(event, MSG_NOTIFICATION);
+	sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
 
 	ssf = (struct sctp_send_failed *)
 		skb_push(skb, sizeof(struct sctp_send_failed));
@@ -682,8 +684,11 @@
 	/* Embed the event fields inside the cloned skb.  */
 	event = sctp_skb2event(skb);
 
-	/* Initialize event with flags 0.  */
-	sctp_ulpevent_init(event, 0);
+	/* Initialize event with flags 0  and correct length
+	 * Since this is a clone of the original skb, only account for
+	 * the data of this chunk as other chunks will be accounted separately.
+	 */
+	sctp_ulpevent_init(event, 0, skb->len + sizeof(struct sk_buff));
 
 	sctp_ulpevent_receive_data(event, asoc);
 
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 575e556..e1d1442 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -309,7 +309,7 @@
  			if (!new)
  				return NULL;	/* try again later */
 
- 			new->sk = f_frag->sk;
+ 			sctp_skb_set_owner_r(new, f_frag->sk);
 
  			skb_shinfo(new)->frag_list = pos;
  		} else
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 2a78616..7736b23 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -883,30 +883,32 @@
 }
 EXPORT_SYMBOL(xfrm_policy_walk);
 
-/* Find policy to apply to this flow. */
-
+/*
+ * Find policy to apply to this flow.
+ *
+ * Returns 0 if policy found, else an -errno.
+ */
 static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
 			     u8 type, u16 family, int dir)
 {
 	struct xfrm_selector *sel = &pol->selector;
-	int match;
+	int match, ret = -ESRCH;
 
 	if (pol->family != family ||
 	    pol->type != type)
-		return 0;
+		return ret;
 
 	match = xfrm_selector_match(sel, fl, family);
-	if (match) {
-		if (!security_xfrm_policy_lookup(pol, fl->secid, dir))
-			return 1;
-	}
+	if (match)
+		ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
 
-	return 0;
+	return ret;
 }
 
 static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl,
 						     u16 family, u8 dir)
 {
+	int err;
 	struct xfrm_policy *pol, *ret;
 	xfrm_address_t *daddr, *saddr;
 	struct hlist_node *entry;
@@ -922,7 +924,15 @@
 	chain = policy_hash_direct(daddr, saddr, family, dir);
 	ret = NULL;
 	hlist_for_each_entry(pol, entry, chain, bydst) {
-		if (xfrm_policy_match(pol, fl, type, family, dir)) {
+		err = xfrm_policy_match(pol, fl, type, family, dir);
+		if (err) {
+			if (err == -ESRCH)
+				continue;
+			else {
+				ret = ERR_PTR(err);
+				goto fail;
+			}
+		} else {
 			ret = pol;
 			priority = ret->priority;
 			break;
@@ -930,36 +940,53 @@
 	}
 	chain = &xfrm_policy_inexact[dir];
 	hlist_for_each_entry(pol, entry, chain, bydst) {
-		if (xfrm_policy_match(pol, fl, type, family, dir) &&
-		    pol->priority < priority) {
+		err = xfrm_policy_match(pol, fl, type, family, dir);
+		if (err) {
+			if (err == -ESRCH)
+				continue;
+			else {
+				ret = ERR_PTR(err);
+				goto fail;
+			}
+		} else if (pol->priority < priority) {
 			ret = pol;
 			break;
 		}
 	}
 	if (ret)
 		xfrm_pol_hold(ret);
+fail:
 	read_unlock_bh(&xfrm_policy_lock);
 
 	return ret;
 }
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp)
 {
 	struct xfrm_policy *pol;
+	int err = 0;
 
 #ifdef CONFIG_XFRM_SUB_POLICY
 	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir);
-	if (pol)
+	if (IS_ERR(pol)) {
+		err = PTR_ERR(pol);
+		pol = NULL;
+	}
+	if (pol || err)
 		goto end;
 #endif
 	pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir);
-
+	if (IS_ERR(pol)) {
+		err = PTR_ERR(pol);
+		pol = NULL;
+	}
 #ifdef CONFIG_XFRM_SUB_POLICY
 end:
 #endif
 	if ((*objp = (void *) pol) != NULL)
 		*obj_refp = &pol->refcnt;
+	return err;
 }
 
 static inline int policy_to_flow_dir(int dir)
@@ -989,12 +1016,16 @@
 						sk->sk_family);
  		int err = 0;
 
-		if (match)
-		  err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir));
-
- 		if (match && !err)
-			xfrm_pol_hold(pol);
-		else
+		if (match) {
+			err = security_xfrm_policy_lookup(pol, fl->secid,
+					policy_to_flow_dir(dir));
+			if (!err)
+				xfrm_pol_hold(pol);
+			else if (err == -ESRCH)
+				pol = NULL;
+			else
+				pol = ERR_PTR(err);
+		} else
 			pol = NULL;
 	}
 	read_unlock_bh(&xfrm_policy_lock);
@@ -1286,8 +1317,11 @@
 	pol_dead = 0;
 	xfrm_nr = 0;
 
-	if (sk && sk->sk_policy[1])
+	if (sk && sk->sk_policy[1]) {
 		policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+		if (IS_ERR(policy))
+			return PTR_ERR(policy);
+	}
 
 	if (!policy) {
 		/* To accelerate a bit...  */
@@ -1297,6 +1331,8 @@
 
 		policy = flow_cache_lookup(fl, dst_orig->ops->family,
 					   dir, xfrm_policy_lookup);
+		if (IS_ERR(policy))
+			return PTR_ERR(policy);
 	}
 
 	if (!policy)
@@ -1343,6 +1379,10 @@
 							    fl, family,
 							    XFRM_POLICY_OUT);
 			if (pols[1]) {
+				if (IS_ERR(pols[1])) {
+					err = PTR_ERR(pols[1]);
+					goto error;
+				}
 				if (pols[1]->action == XFRM_POLICY_BLOCK) {
 					err = -EPERM;
 					goto error;
@@ -1574,13 +1614,19 @@
 	}
 
 	pol = NULL;
-	if (sk && sk->sk_policy[dir])
+	if (sk && sk->sk_policy[dir]) {
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+		if (IS_ERR(pol))
+			return 0;
+	}
 
 	if (!pol)
 		pol = flow_cache_lookup(&fl, family, fl_dir,
 					xfrm_policy_lookup);
 
+	if (IS_ERR(pol))
+		return 0;
+
 	if (!pol) {
 		if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
 			xfrm_secpath_reject(xerr_idx, skb, &fl);
@@ -1599,6 +1645,8 @@
 						    &fl, family,
 						    XFRM_POLICY_IN);
 		if (pols[1]) {
+			if (IS_ERR(pols[1]))
+				return 0;
 			pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec;
 			npols ++;
 		}
@@ -1706,7 +1754,7 @@
 
 static int stale_bundle(struct dst_entry *dst)
 {
-	return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
+	return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
 }
 
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -1828,7 +1876,8 @@
  * still valid.
  */
 
-int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict)
+int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
+		struct flowi *fl, int family, int strict)
 {
 	struct dst_entry *dst = &first->u.dst;
 	struct xfrm_dst *last;
@@ -1845,7 +1894,7 @@
 
 		if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
 			return 0;
-		if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
+		if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol))
 			return 0;
 		if (dst->xfrm->km.state != XFRM_STATE_VALID)
 			return 0;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d54b3a7..2b2e59d 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1992,15 +1992,6 @@
 	xp->type = XFRM_POLICY_TYPE_MAIN;
 	copy_templates(xp, ut, nr);
 
-	if (!xp->security) {
-		int err = security_xfrm_sock_policy_alloc(xp, sk);
-		if (err) {
-			kfree(xp);
-			*dir = err;
-			return NULL;
-		}
-	}
-
 	*dir = p->dir;
 
 	return xp;
diff --git a/security/dummy.c b/security/dummy.c
index aeee705..43874c1 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -881,7 +881,8 @@
 	return 1;
 }
 
-static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+				struct xfrm_policy *xp)
 {
 	return 1;
 }
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 81eb598..526b280 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,8 @@
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
 			struct xfrm_policy *xp, struct flowi *fl);
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+			struct xfrm_policy *xp);
 
 
 /*
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index b188953..ba48961 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -618,6 +618,7 @@
 			c = c->next;
 			ocontext_destroy(ctmp,i);
 		}
+		p->ocontexts[i] = NULL;
 	}
 
 	g = p->genfs;
@@ -633,6 +634,7 @@
 		g = g->next;
 		kfree(gtmp);
 	}
+	p->genfs = NULL;
 
 	cond_policydb_destroy(p);
 
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0c219a1..18274b0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2172,7 +2172,12 @@
  */
 static void selinux_netlbl_cache_free(const void *data)
 {
-	struct netlbl_cache *cache = NETLBL_CACHE(data);
+	struct netlbl_cache *cache;
+
+	if (data == NULL)
+		return;
+
+	cache = NETLBL_CACHE(data);
 	switch (cache->type) {
 	case NETLBL_CACHE_T_MLS:
 		ebitmap_destroy(&cache->data.mls_label.level[0].cat);
@@ -2197,17 +2202,20 @@
 	struct netlbl_lsm_secattr secattr;
 
 	netlbl_secattr_init(&secattr);
+	secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
+	if (secattr.cache == NULL)
+		goto netlbl_cache_add_return;
 
 	cache = kzalloc(sizeof(*cache),	GFP_ATOMIC);
 	if (cache == NULL)
-		goto netlbl_cache_add_failure;
-	secattr.cache.free = selinux_netlbl_cache_free;
-	secattr.cache.data = (void *)cache;
+		goto netlbl_cache_add_return;
+	secattr.cache->free = selinux_netlbl_cache_free;
+	secattr.cache->data = (void *)cache;
 
 	cache->type = NETLBL_CACHE_T_MLS;
 	if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
 			&ctx->range.level[0].cat) != 0)
-		goto netlbl_cache_add_failure;
+		goto netlbl_cache_add_return;
 	cache->data.mls_label.level[1].cat.highbit =
 		cache->data.mls_label.level[0].cat.highbit;
 	cache->data.mls_label.level[1].cat.node =
@@ -2215,13 +2223,10 @@
 	cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
 	cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
 
-	if (netlbl_cache_add(skb, &secattr) != 0)
-		goto netlbl_cache_add_failure;
+	netlbl_cache_add(skb, &secattr);
 
-	return;
-
-netlbl_cache_add_failure:
-	netlbl_secattr_destroy(&secattr, 1);
+netlbl_cache_add_return:
+	netlbl_secattr_destroy(&secattr);
 }
 
 /**
@@ -2263,8 +2268,8 @@
 
 	POLICY_RDLOCK;
 
-	if (secattr->cache.data) {
-		cache = NETLBL_CACHE(secattr->cache.data);
+	if (secattr->cache) {
+		cache = NETLBL_CACHE(secattr->cache->data);
 		switch (cache->type) {
 		case NETLBL_CACHE_T_SID:
 			*sid = cache->data.sid;
@@ -2331,7 +2336,7 @@
 			selinux_netlbl_cache_add(skb, &ctx_new);
 		ebitmap_destroy(&ctx_new.range.level[0].cat);
 	} else {
-		*sid = SECINITSID_UNLABELED;
+		*sid = SECSID_NULL;
 		rc = 0;
 	}
 
@@ -2369,7 +2374,7 @@
 						   &secattr,
 						   base_sid,
 						   sid);
-	netlbl_secattr_destroy(&secattr, 0);
+	netlbl_secattr_destroy(&secattr);
 
 	return rc;
 }
@@ -2415,7 +2420,7 @@
 	if (rc == 0)
 		sksec->nlbl_state = NLBL_LABELED;
 
-	netlbl_secattr_destroy(&secattr, 0);
+	netlbl_secattr_destroy(&secattr);
 
 netlbl_socket_setsid_return:
 	POLICY_RDUNLOCK;
@@ -2514,10 +2519,10 @@
 	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
 	    selinux_netlbl_secattr_to_sid(NULL,
 					  &secattr,
-					  sksec->sid,
+					  SECINITSID_UNLABELED,
 					  &nlbl_peer_sid) == 0)
 		sksec->peer_sid = nlbl_peer_sid;
-	netlbl_secattr_destroy(&secattr, 0);
+	netlbl_secattr_destroy(&secattr);
 
 	sksec->nlbl_state = NLBL_REQUIRE;
 
@@ -2547,9 +2552,6 @@
 	if (rc != 0)
 		return SECSID_NULL;
 
-	if (peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
 	return peer_sid;
 }
 
@@ -2611,11 +2613,13 @@
 	u32 netlbl_sid;
 	u32 recv_perm;
 
-	rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
+	rc = selinux_netlbl_skbuff_getsid(skb,
+					  SECINITSID_UNLABELED,
+					  &netlbl_sid);
 	if (rc != 0)
 		return rc;
 
-	if (netlbl_sid == SECINITSID_UNLABELED)
+	if (netlbl_sid == SECSID_NULL)
 		return 0;
 
 	switch (sksec->sclass) {
@@ -2653,10 +2657,6 @@
 u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
 {
 	struct sk_security_struct *sksec = sock->sk->sk_security;
-
-	if (sksec->peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
 	return sksec->peer_sid;
 }
 
@@ -2672,16 +2672,10 @@
 u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
 {
 	int peer_sid;
-	struct sock *sk = skb->sk;
-	struct inode_security_struct *isec;
 
-	if (sk == NULL || sk->sk_socket == NULL)
-		return SECSID_NULL;
-
-	isec = SOCK_INODE(sk->sk_socket)->i_security;
-	if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
-		return SECSID_NULL;
-	if (peer_sid == SECINITSID_UNLABELED)
+	if (selinux_netlbl_skbuff_getsid(skb,
+					 SECINITSID_UNLABELED,
+					 &peer_sid) != 0)
 		return SECSID_NULL;
 
 	return peer_sid;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 3e742b8..675b995 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -77,8 +77,8 @@
  */
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
 {
-	int rc = 0;
-	u32 sel_sid = SECINITSID_UNLABELED;
+	int rc;
+	u32 sel_sid;
 	struct xfrm_sec_ctx *ctx;
 
 	/* Context sid is either set to label or ANY_ASSOC */
@@ -88,11 +88,21 @@
 
 		sel_sid = ctx->ctx_sid;
 	}
+	else
+		/*
+		 * All flows should be treated as polmatch'ing an
+		 * otherwise applicable "non-labeled" policy. This
+		 * would prevent inadvertent "leaks".
+		 */
+		return 0;
 
 	rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__POLMATCH,
 			  NULL);
 
+	if (rc == -EACCES)
+		rc = -ESRCH;
+
 	return rc;
 }
 
@@ -108,15 +118,20 @@
 	u32 pol_sid;
 	int err;
 
-	if (x->security)
-		state_sid = x->security->ctx_sid;
-	else
-		state_sid = SECINITSID_UNLABELED;
-
-	if (xp->security)
+	if (xp->security) {
+		if (!x->security)
+			/* unlabeled SA and labeled policy can't match */
+			return 0;
+		else
+			state_sid = x->security->ctx_sid;
 		pol_sid = xp->security->ctx_sid;
-	else
-		pol_sid = SECINITSID_UNLABELED;
+	} else
+		if (x->security)
+			/* unlabeled policy and labeled SA can't match */
+			return 0;
+		else
+			/* unlabeled policy and unlabeled SA match all flows */
+			return 1;
 
 	err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__POLMATCH,
@@ -125,7 +140,11 @@
 	if (err)
 		return 0;
 
-	return selinux_xfrm_flow_state_match(fl, x);
+	err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__SENDTO,
+			  NULL)? 0:1;
+
+	return err;
 }
 
 /*
@@ -133,12 +152,22 @@
  * can use a given security association.
  */
 
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+				  struct xfrm_policy *xp)
 {
 	int rc = 0;
 	u32 sel_sid = SECINITSID_UNLABELED;
 	struct xfrm_sec_ctx *ctx;
 
+	if (!xp->security)
+		if (!xfrm->security)
+			return 1;
+		else
+			return 0;
+	else
+		if (!xfrm->security)
+			return 0;
+
 	/* Context sid is either set to label or ANY_ASSOC */
 	if ((ctx = xfrm->security)) {
 		if (!selinux_authorizable_ctx(ctx))