## Automatically generated incremental diff
## From:   linux-2.5.64-bk4
## To:     linux-2.5.64-bk5
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.64-bk4/Documentation/cpu-freq/core.txt linux-2.5.64-bk5/Documentation/cpu-freq/core.txt
--- linux-2.5.64-bk4/Documentation/cpu-freq/core.txt	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk5/Documentation/cpu-freq/core.txt	Mon Mar 31 12:27:40 2003
@@ -35,6 +35,10 @@
 kernel "constant" loops_per_jiffy is updated on frequency changes
 here.
 
+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
+which make sure that the cpufreq processor driver is correctly
+registered with the core, and will not be unloaded until
+cpufreq_put_cpu is called.
 
 2. CPUFreq notifiers
 ====================
diff -urN linux-2.5.64-bk4/Documentation/cpu-freq/cpu-drivers.txt linux-2.5.64-bk5/Documentation/cpu-freq/cpu-drivers.txt
--- linux-2.5.64-bk4/Documentation/cpu-freq/cpu-drivers.txt	Tue Mar  4 19:29:55 2003
+++ linux-2.5.64-bk5/Documentation/cpu-freq/cpu-drivers.txt	Mon Mar 31 12:27:40 2003
@@ -63,6 +63,9 @@
 
 cpufreq_driver.exit -		A pointer to a per-CPU cleanup function.
 
+cpufreq_driver.attr -		A pointer to a NULL-terminated list of
+				"struct freq_attr" which allow to
+				export values to sysfs.
 
 
 1.2 Per-CPU Initialization
diff -urN linux-2.5.64-bk4/Documentation/cpu-freq/user-guide.txt linux-2.5.64-bk5/Documentation/cpu-freq/user-guide.txt
--- linux-2.5.64-bk4/Documentation/cpu-freq/user-guide.txt	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk5/Documentation/cpu-freq/user-guide.txt	Mon Mar 31 12:27:40 2003
@@ -114,9 +114,9 @@
 ------------------------------
 
 The preferred interface is located in the sysfs filesystem. If you
-mounted it at /sys, the cpufreq interface is located in the 
-cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first
-CPU).
+mounted it at /sys, the cpufreq interface is located in a subdirectory
+"cpufreq" within the cpu-device directory
+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
 
 cpuinfo_min_freq :		this file shows the minimum operating
 				frequency the processor can run at(in kHz) 
@@ -125,7 +125,7 @@
 scaling_driver :		this file shows what cpufreq driver is
 				used to set the frequency on this CPU
 
-available_scaling_governors :	this file shows the CPUfreq governors
+scaling_available_governors :	this file shows the CPUfreq governors
 				available in this kernel. You can see the
 				currently activated governor in
 
diff -urN linux-2.5.64-bk4/Makefile linux-2.5.64-bk5/Makefile
--- linux-2.5.64-bk4/Makefile	Mon Mar 31 12:27:34 2003
+++ linux-2.5.64-bk5/Makefile	Mon Mar 31 12:27:40 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 64
-EXTRAVERSION = bk4
+EXTRAVERSION = bk5
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.64-bk4/arch/alpha/oprofile/op_model_ev4.c linux-2.5.64-bk5/arch/alpha/oprofile/op_model_ev4.c
--- linux-2.5.64-bk4/arch/alpha/oprofile/op_model_ev4.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk5/arch/alpha/oprofile/op_model_ev4.c	Mon Mar 31 12:27:40 2003
@@ -34,7 +34,7 @@
 	   for these "disabled" counter overflows are ignored by the
 	   interrupt handler.
 
-	   This is most irritating, becuase the hardware *can* enable and
+	   This is most irritating, because the hardware *can* enable and
 	   disable the interrupts for these counters independently, but the
 	   wrperfmon interface doesn't allow it.  */
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/acpi.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/acpi.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/acpi.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/acpi.c	Mon Mar 31 12:27:40 2003
@@ -619,6 +619,7 @@
 	.init		= acpi_cpufreq_cpu_init,
 	.exit		= acpi_cpufreq_cpu_exit,
 	.name		= "acpi-cpufreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/elanfreq.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/elanfreq.c	Mon Mar 31 12:27:40 2003
@@ -250,6 +250,7 @@
 	.target 	= elanfreq_target,
 	.init		= elanfreq_cpu_init,
 	.name		= "elanfreq",
+	.owner		= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	Mon Mar 31 12:27:40 2003
@@ -451,6 +451,7 @@
 	.target		= cpufreq_gx_target,
 	.init		= cpufreq_gx_cpu_init,
 	.name		= "gx-suspmod",
+	.owner		= THIS_MODULE,
 };
 
 static int __init cpufreq_gx_init(void)
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/longhaul.c	Tue Mar  4 19:28:57 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/longhaul.c	Mon Mar 31 12:27:40 2003
@@ -649,6 +649,7 @@
 	.target 	= longhaul_target,
 	.init		= longhaul_cpu_init,
 	.name		= "longhaul",
+	.owner		= THIS_MODULE,
 };
 
 static int __init longhaul_init (void)
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/longrun.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/longrun.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/longrun.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/longrun.c	Mon Mar 31 12:27:40 2003
@@ -253,6 +253,7 @@
 	.setpolicy 	= longrun_set_policy,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
+	.owner		= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Tue Mar  4 19:29:36 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	Mon Mar 31 12:27:40 2003
@@ -214,6 +214,7 @@
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
 	}
+	cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 	
 	/* cpuinfo and default policy values */
 	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -226,9 +227,14 @@
 
 static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
 {
+	cpufreq_frequency_table_put_attr(policy->cpu);    
 	return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
 }
 
+static struct freq_attr* p4clockmod_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
 
 static struct cpufreq_driver p4clockmod_driver = {
 	.verify 	= cpufreq_p4_verify,
@@ -236,6 +242,8 @@
 	.init		= cpufreq_p4_cpu_init,
 	.exit		= cpufreq_p4_cpu_exit,
 	.name		= "p4-clockmod",
+	.owner		= THIS_MODULE,
+	.attr		= p4clockmod_attr,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/powernow-k6.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Tue Mar  4 19:28:59 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	Mon Mar 31 12:27:40 2003
@@ -190,6 +190,7 @@
 	.init		= powernow_k6_cpu_init,
 	.exit		= powernow_k6_cpu_exit,
 	.name		= "powernow-k6",
+	.owner		= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Tue Mar  4 19:28:54 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Mon Mar 31 12:27:40 2003
@@ -377,6 +377,7 @@
 	.target 	= powernow_target,
 	.init		= powernow_cpu_init,
 	.name		= "powernow-k7",
+	.owner		= THIS_MODULE,
 };
 
 static int __init powernow_init (void)
diff -urN linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/speedstep.c linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- linux-2.5.64-bk4/arch/i386/kernel/cpu/cpufreq/speedstep.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/cpu/cpufreq/speedstep.c	Mon Mar 31 12:27:40 2003
@@ -29,7 +29,6 @@
 
 #include <asm/msr.h>
 
-
 /* speedstep_chipset:
  *   It is necessary to know which chipset is used. As accesses to 
  * this device occur at various places in this module, we need a 
@@ -40,7 +39,7 @@
 
 #define SPEEDSTEP_CHIPSET_ICH2M         0x00000002
 #define SPEEDSTEP_CHIPSET_ICH3M         0x00000003
-
+#define SPEEDSTEP_CHIPSET_ICH4M         0x00000004
 
 /* speedstep_processor
  */
@@ -106,6 +105,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -166,6 +166,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 		/* get PMBASE */
 		pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 		if (!(pmbase & 0x01))
@@ -245,6 +246,7 @@
 	switch (speedstep_chipset) {
 	case SPEEDSTEP_CHIPSET_ICH2M:
 	case SPEEDSTEP_CHIPSET_ICH3M:
+	case SPEEDSTEP_CHIPSET_ICH4M:
 	{
 		u16             value = 0;
 
@@ -277,6 +279,14 @@
 static unsigned int speedstep_detect_chipset (void)
 {
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82801DB_12, 
+			      PCI_ANY_ID,
+			      PCI_ANY_ID,
+			      NULL);
+	if (speedstep_chipset_dev)
+		return SPEEDSTEP_CHIPSET_ICH4M;
+
+	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82801CA_12, 
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
@@ -658,6 +668,7 @@
 	.verify 	= speedstep_verify,
 	.target 	= speedstep_target,
 	.init		= speedstep_cpu_init,
+	.owner		= THIS_MODULE,
 };
 
 
diff -urN linux-2.5.64-bk4/arch/i386/kernel/i387.c linux-2.5.64-bk5/arch/i386/kernel/i387.c
--- linux-2.5.64-bk4/arch/i386/kernel/i387.c	Tue Mar  4 19:29:56 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/i387.c	Mon Mar 31 12:27:40 2003
@@ -52,24 +52,6 @@
  * FPU lazy state save handling.
  */
 
-static inline void __save_init_fpu( struct task_struct *tsk )
-{
-	if ( cpu_has_fxsr ) {
-		asm volatile( "fxsave %0 ; fnclex"
-			      : "=m" (tsk->thread.i387.fxsave) );
-	} else {
-		asm volatile( "fnsave %0 ; fwait"
-			      : "=m" (tsk->thread.i387.fsave) );
-	}
-	clear_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
-
-void save_init_fpu( struct task_struct *tsk )
-{
-	__save_init_fpu(tsk);
-	stts();
-}
-
 void kernel_fpu_begin(void)
 {
 	preempt_disable();
diff -urN linux-2.5.64-bk4/arch/i386/kernel/sysenter.c linux-2.5.64-bk5/arch/i386/kernel/sysenter.c
--- linux-2.5.64-bk4/arch/i386/kernel/sysenter.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/sysenter.c	Mon Mar 31 12:27:40 2003
@@ -40,6 +40,7 @@
 	int cpu = get_cpu();
 	struct tss_struct *tss = init_tss + cpu;
 
+	tss->ss1 = __KERNEL_CS;
 	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0);
 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
diff -urN linux-2.5.64-bk4/arch/i386/kernel/vm86.c linux-2.5.64-bk5/arch/i386/kernel/vm86.c
--- linux-2.5.64-bk4/arch/i386/kernel/vm86.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk5/arch/i386/kernel/vm86.c	Mon Mar 31 12:27:40 2003
@@ -291,7 +291,7 @@
 
 	tss = init_tss + smp_processor_id();
 	tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
-	disable_sysenter();
+	disable_sysenter(tss);
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
diff -urN linux-2.5.64-bk4/arch/i386/oprofile/op_model_athlon.c linux-2.5.64-bk5/arch/i386/oprofile/op_model_athlon.c
--- linux-2.5.64-bk4/arch/i386/oprofile/op_model_athlon.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk5/arch/i386/oprofile/op_model_athlon.c	Mon Mar 31 12:27:40 2003
@@ -104,10 +104,11 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
  
diff -urN linux-2.5.64-bk4/arch/i386/oprofile/op_model_p4.c linux-2.5.64-bk5/arch/i386/oprofile/op_model_p4.c
--- linux-2.5.64-bk4/arch/i386/oprofile/op_model_p4.c	Mon Mar 31 12:27:34 2003
+++ linux-2.5.64-bk5/arch/i386/oprofile/op_model_p4.c	Mon Mar 31 12:27:40 2003
@@ -608,13 +608,14 @@
  			CTR_WRITE(reset_value[i], real);
 			/* P4 quirk: you have to re-unmask the apic vector */
 			apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-			return 1;
 		}
 	}
 
 	/* P4 quirk: you have to re-unmask the apic vector */
 	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
-	return 0;
+
+	/* See op_model_ppro.c */
+	return 1;
 }
 
 
diff -urN linux-2.5.64-bk4/arch/i386/oprofile/op_model_ppro.c linux-2.5.64-bk5/arch/i386/oprofile/op_model_ppro.c
--- linux-2.5.64-bk4/arch/i386/oprofile/op_model_ppro.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk5/arch/i386/oprofile/op_model_ppro.c	Mon Mar 31 12:27:40 2003
@@ -98,10 +98,17 @@
 		if (CTR_OVERFLOWED(low)) {
 			oprofile_add_sample(eip, is_kernel, i, cpu);
 			CTR_WRITE(reset_value[i], msrs, i);
-			return 1;
 		}
 	}
-	return 0;
+
+	/* We can't work out if we really handled an interrupt. We
+	 * might have caught a *second* counter just after overflowing
+	 * the interrupt for this counter then arrives
+	 * and we don't find a counter that's overflowed, so we
+	 * would return 0 and get dazed + confused. Instead we always
+	 * assume we found an overflow. This sucks.
+	 */
+	return 1;
 }
 
  
diff -urN linux-2.5.64-bk4/arch/sparc64/kernel/us3_cpufreq.c linux-2.5.64-bk5/arch/sparc64/kernel/us3_cpufreq.c
--- linux-2.5.64-bk4/arch/sparc64/kernel/us3_cpufreq.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk5/arch/sparc64/kernel/us3_cpufreq.c	Mon Mar 31 12:27:43 2003
@@ -276,6 +276,7 @@
 		driver->target = us3freq_target;
 		driver->init = us3freq_cpu_init;
 		driver->exit = us3freq_cpu_exit;
+		driver->owner = THIS_MODULE,
 		strcpy(driver->name, "UltraSPARC-III");
 
 		cpufreq_us3_driver = driver;
diff -urN linux-2.5.64-bk4/drivers/cpufreq/freq_table.c linux-2.5.64-bk5/drivers/cpufreq/freq_table.c
--- linux-2.5.64-bk4/drivers/cpufreq/freq_table.c	Tue Mar  4 19:29:35 2003
+++ linux-2.5.64-bk5/drivers/cpufreq/freq_table.c	Mon Mar 31 12:27:44 2003
@@ -77,56 +77,6 @@
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index)
-{
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	unsigned int i;
-
-	switch (policy->policy) {
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal.frequency = 0;
-		break;
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal.frequency = ~0;
-		break;
-	}
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq < policy->min) || (freq > policy->max))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (optimal.frequency <= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal.frequency >= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		}
-	}
-	if (optimal.index > i)
-		return -EINVAL;
-
-	*index = optimal.index;
-	
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
-
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
@@ -197,6 +147,56 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
 
+static struct cpufreq_frequency_table *show_table[NR_CPUS];
+/**
+ * show_scaling_governor - show the current policy for the specified CPU
+ */
+static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
+{
+	unsigned int i = 0;
+	unsigned int cpu = policy->cpu;
+	ssize_t count = 0;
+	struct cpufreq_frequency_table *table;
+
+	if (!show_table[cpu])
+		return -ENODEV;
+
+	table = show_table[cpu];
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+		count += sprintf(&buf[count], "%d ", table[i].frequency);
+	}
+	count += sprintf(&buf[count], "\n");
+
+	return count;
+
+}
+
+struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
+	.attr = { .name = "scaling_available_frequencies", .mode = 0444 },
+	.show = show_available_freqs,
+};
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
+
+/*
+ * if you use these, you must assure that the frequency table is valid
+ * all the time between get_attr and put_attr!
+ */
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu)
+{
+	show_table[cpu] = table;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu)
+{
+	show_table[cpu] = NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
+
 
 MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
diff -urN linux-2.5.64-bk4/drivers/cpufreq/userspace.c linux-2.5.64-bk5/drivers/cpufreq/userspace.c
--- linux-2.5.64-bk4/drivers/cpufreq/userspace.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/drivers/cpufreq/userspace.c	Mon Mar 31 12:27:44 2003
@@ -23,6 +23,7 @@
 #include <linux/sysctl.h>
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/sysfs.h>
 
 #include <asm/uaccess.h>
 
@@ -112,7 +113,7 @@
 	if (freq > cpu_max_freq[cpu])
 		freq = cpu_max_freq[cpu];
 
-	ret = cpufreq_driver_target_l(&current_policy[cpu], freq, 
+	ret = cpufreq_driver_target(&current_policy[cpu], freq, 
 	      CPUFREQ_RELATION_L);
 
  err:
@@ -465,23 +466,14 @@
 
 
 /************************** sysfs interface ************************/
-static inline int to_cpu_nr (struct device *dev)
+static ssize_t show_speed (struct cpufreq_policy *policy, char *buf)
 {
-	struct sys_device * cpu_sys_dev = container_of(dev, struct sys_device, dev);
-	return (cpu_sys_dev->id);
-}
-
-static ssize_t show_speed (struct device *dev, char *buf)
-{
-	unsigned int cpu = to_cpu_nr(dev);
-
-	return sprintf (buf, "%u\n", cpu_cur_freq[cpu]);
+	return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]);
 }
 
 static ssize_t 
-store_speed (struct device *dev, const char *buf, size_t count) 
+store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) 
 {
-	unsigned int cpu = to_cpu_nr(dev);
 	unsigned int freq = 0;
 	unsigned int ret;
 
@@ -489,13 +481,16 @@
 	if (ret != 1)
 		return -EINVAL;
 
-	cpufreq_set(freq, cpu);
+	cpufreq_set(freq, policy->cpu);
 
 	return count;
 }
 
-static DEVICE_ATTR(scaling_setspeed, (S_IRUGO | S_IWUSR), show_speed, store_speed);
-
+static struct freq_attr freq_attr_scaling_setspeed = {
+	.attr = { .name = "scaling_setspeed", .mode = 0644 },
+	.show = show_speed,
+	.store = store_speed,
+};
 
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 				   unsigned int event)
@@ -511,7 +506,7 @@
 		cpu_min_freq[cpu] = policy->min;
 		cpu_max_freq[cpu] = policy->max;
 		cpu_cur_freq[cpu] = policy->cur;
-		device_create_file (policy->dev, &dev_attr_scaling_setspeed);
+		sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
 		up(&userspace_sem);
 		break;
@@ -520,7 +515,7 @@
 		cpu_is_managed[cpu] = 0;
 		cpu_min_freq[cpu] = 0;
 		cpu_max_freq[cpu] = 0;
-		device_remove_file (policy->dev, &dev_attr_scaling_setspeed);
+		sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);
 		up(&userspace_sem);
 		module_put(THIS_MODULE);
 		break;
diff -urN linux-2.5.64-bk4/drivers/oprofile/cpu_buffer.c linux-2.5.64-bk5/drivers/oprofile/cpu_buffer.c
--- linux-2.5.64-bk4/drivers/oprofile/cpu_buffer.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/drivers/oprofile/cpu_buffer.c	Mon Mar 31 12:27:44 2003
@@ -85,9 +85,6 @@
 	unsigned long head = b->head_pos;
 	unsigned long tail = b->tail_pos;
 
-	if (tail == head)
-		return b->buffer_size;
-
 	if (tail > head)
 		return tail - head;
 
diff -urN linux-2.5.64-bk4/drivers/scsi/Kconfig linux-2.5.64-bk5/drivers/scsi/Kconfig
--- linux-2.5.64-bk4/drivers/scsi/Kconfig	Tue Mar  4 19:29:35 2003
+++ linux-2.5.64-bk5/drivers/scsi/Kconfig	Mon Mar 31 12:27:44 2003
@@ -946,16 +946,6 @@
 	  Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
 	  information.
 
-config SCSI_ZALON
-	tristate "Zalon SCSI support"
-	depends on GSC && SCSI
-	help
-	  The Zalon is a GSC/HSC bus interface chip that sits between the
-	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
-	  C110, J200, J210 and some D, K & R-class machines.  It's also
-	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
-	  Say Y here if you have one of these machines or cards.
-
 config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
 	int "DMA addressing mode"
 	depends on SCSI_SYM53C8XX_2
@@ -1010,9 +1000,19 @@
 	  If you say Y here, the driver will preferently use normal IO rather than 
 	  memory mapped IO.
 
+config SCSI_ZALON
+	tristate "Zalon SCSI support"
+	depends on GSC && SCSI
+	help
+	  The Zalon is a GSC/HSC bus interface chip that sits between the
+	  PA-RISC processor and the NCR 53c720 SCSI controller on C100,
+	  C110, J200, J210 and some D, K & R-class machines.  It's also
+	  used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
+	  Say Y here if you have one of these machines or cards.
+
 config SCSI_NCR53C8XX
 	tristate "NCR53C8XX SCSI support"
-	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI
+	depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI
 	---help---
 	  This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
 	  of PCI-SCSI controllers.  This driver supports parity checking,
diff -urN linux-2.5.64-bk4/drivers/scsi/fdomain.c linux-2.5.64-bk5/drivers/scsi/fdomain.c
--- linux-2.5.64-bk4/drivers/scsi/fdomain.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk5/drivers/scsi/fdomain.c	Mon Mar 31 12:27:44 2003
@@ -271,13 +271,8 @@
 
  **************************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
-#include <linux/config.h>	/* for CONFIG_PCI */
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/blk.h>
@@ -295,9 +290,13 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "fdomain.h"
+
+MODULE_AUTHOR("Rickard E. Faith");
+MODULE_DESCRIPTION("Future domain SCSI driver");
+MODULE_LICENSE("GPL");
+
   
-#define VERSION          "$Revision: 5.50 $"
+#define VERSION          "$Revision: 5.51 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -421,15 +420,12 @@
 
 static void              do_fdomain_16x0_intr( int irq, void *dev_id,
 					    struct pt_regs * regs );
+int		 	fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
-#ifdef MODULE
-				/* Allow insmod parameters to be like LILO
-                                   parameters.  For example:
-				   insmod fdomain fdomain=0x140,11
-				*/
+/* Allow insmod parameters to be like LILO parameters.  For example:
+   insmod fdomain fdomain=0x140,11 */
 static char * fdomain = NULL;
 MODULE_PARM(fdomain, "s");
-#endif
 
 static unsigned long addresses[] = {
    0xc8000,
@@ -561,7 +557,7 @@
    printk( "\n" );
 }
 
-static int __init fdomain_setup(char *str)
+int __init fdomain_setup(char *str)
 {
 	int ints[4];
 
@@ -862,7 +858,7 @@
 }
 #endif
 
-static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
 {
    int              retcode;
    struct Scsi_Host *shpnt;
@@ -879,13 +875,6 @@
    unsigned char    buf[buflen];
 #endif
 
-   tpnt->proc_name = "fdomain";
-
-#ifdef MODULE
-	if (fdomain)
-		fdomain_setup(fdomain);
-#endif
-   
    if (setup_called) {
 #if DEBUG_DETECT
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
@@ -895,7 +884,7 @@
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
-	 return 0;
+	 return NULL;
       }
    } else {
       int flag = 0;
@@ -910,7 +899,7 @@
 
 	 if (!flag) {
 	    printk( "scsi: <fdomain> Detection failed (no card)\n" );
-	    return 0;
+	    return NULL;
 	 }
       }
    }
@@ -936,7 +925,7 @@
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
-      return 0;
+      return NULL;
    }
 
    if (this_id) {
@@ -957,7 +946,7 @@
 
    shpnt = scsi_register( tpnt, 0 );
    if(shpnt == NULL)
-   	return 0;
+   	return NULL;
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -967,7 +956,7 @@
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
-      return 0;
+      return NULL;
    } else {
       /* Register the IRQ with the kernel */
 
@@ -988,7 +977,7 @@
 	    printk(KERN_ERR "                Send mail to faith@acm.org\n" );
 	 }
 	 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
-	 return 0;
+	 return NULL;
       }
    }
 
@@ -1048,7 +1037,14 @@
    }
 #endif
 
-   return 1;			/* Maximum of one adapter will be detected. */
+   return shpnt;
+}
+
+static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+{
+	if (fdomain)
+		fdomain_setup(fdomain);
+	return (__fdomain_16x0_detect(tpnt) != NULL);
 }
 
 static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
@@ -1150,8 +1146,9 @@
 {
    int           status;
    unsigned long timeout;
+#if ERRORS_ONLY
    static int    flag = 0;
-
+#endif
 
    outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
    outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port );
@@ -1574,6 +1571,7 @@
 
 /* End of code derived from Tommy Thorn's work. */
 
+#if DEBUG_ABORT
 static void print_info(Scsi_Cmnd *SCpnt)
 {
    unsigned int imr;
@@ -1643,6 +1641,7 @@
 	 printk( "Configuration 2  = 0x%02x\n",
 		 inb( port_base + Configuration2 ) );
 }
+#endif
 
 static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
 {
@@ -1670,7 +1669,7 @@
    return SUCCESS;
 }
 
-static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
+int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
 {
    outb( 1, SCSI_Cntl_port );
    do_pause( 2 );
@@ -1866,9 +1865,29 @@
 	return 0;
 }
 
-MODULE_LICENSE("GPL");
-
-/* Eventually this will go into an include file, but this will be later */
-static Scsi_Host_Template driver_template = FDOMAIN_16X0;
+Scsi_Host_Template fdomain_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "fdomain",
+	.proc_name		= "fdomain",
+	.proc_info		= fdomain_16x0_proc_info,
+	.detect			= fdomain_16x0_detect,
+	.info			= fdomain_16x0_info,
+	.command		= fdomain_16x0_command,
+	.queuecommand		= fdomain_16x0_queue,
+	.eh_abort_handler	= fdomain_16x0_abort,
+	.eh_bus_reset_handler	= fdomain_16x0_bus_reset,
+	.eh_device_reset_handler = fdomain_16x0_device_reset,
+	.eh_host_reset_handler	= fdomain_16x0_host_reset,
+	.bios_param		= fdomain_16x0_biosparam,
+	.release		= fdomain_16x0_release,
+	.can_queue		= 1,
+	.this_id		= 6,
+	.sg_tablesize		= 64,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template fdomain_driver_template
 #include "scsi_module.c"
+#endif
diff -urN linux-2.5.64-bk4/drivers/scsi/fdomain.h linux-2.5.64-bk5/drivers/scsi/fdomain.h
--- linux-2.5.64-bk4/drivers/scsi/fdomain.h	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk5/drivers/scsi/fdomain.h	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-/* fdomain.h -- Header for Future Domain TMC-16x0 driver
- * Created: Sun May  3 18:47:33 1992 by faith@cs.unc.edu
- * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org
- * Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
- *
- * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#ifndef _FDOMAIN_H
-#define _FDOMAIN_H
-
-static int        fdomain_16x0_detect( Scsi_Host_Template *);
-static int        fdomain_16x0_command( Scsi_Cmnd *);
-static int        fdomain_16x0_abort(Scsi_Cmnd *);
-static const char *fdomain_16x0_info(struct Scsi_Host *);
-static int        fdomain_16x0_bus_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_host_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_device_reset(Scsi_Cmnd *); 
-static int        fdomain_16x0_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int        fdomain_16x0_biosparam(struct scsi_device *,
-		struct block_device *, sector_t, int * );
-static int        fdomain_16x0_proc_info(char *buffer, char **start, off_t offset,
-				   int length, int hostno, int inout );
-static int        fdomain_16x0_release(struct Scsi_Host *shpnt);
-
-#define FDOMAIN_16X0 { .proc_info      		= fdomain_16x0_proc_info,           \
-		       .detect         		= fdomain_16x0_detect,              \
-		       .info           		= fdomain_16x0_info,                \
-		       .command        		= fdomain_16x0_command,             \
-		       .queuecommand   		= fdomain_16x0_queue,               \
-		       .eh_abort_handler	= fdomain_16x0_abort,               \
-		       .eh_bus_reset_handler	= fdomain_16x0_bus_reset,           \
-		       .eh_device_reset_handler	= fdomain_16x0_device_reset,        \
-		       .eh_host_reset_handler	= fdomain_16x0_host_reset,          \
-		       .bios_param		= fdomain_16x0_biosparam,           \
-		       .release			= fdomain_16x0_release,		  \
-		       .can_queue		= 1, 				  \
-		       .this_id  		= 6, 				  \
-		       .sg_tablesize		= 64, 				  \
-		       .cmd_per_lun		= 1, 				  \
-		       .use_clustering		= DISABLE_CLUSTERING		  \
-}
-#endif
diff -urN linux-2.5.64-bk4/drivers/scsi/ncr53c8xx.c linux-2.5.64-bk5/drivers/scsi/ncr53c8xx.c
--- linux-2.5.64-bk4/drivers/scsi/ncr53c8xx.c	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk5/drivers/scsi/ncr53c8xx.c	Mon Mar 31 12:27:44 2003
@@ -5024,7 +5024,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	ccb_p cp;
@@ -5160,7 +5159,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -8935,7 +8933,6 @@
 }
 
 
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_NCR53C8XX
@@ -8945,7 +8942,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -urN linux-2.5.64-bk4/drivers/scsi/ncr53c8xx.h linux-2.5.64-bk5/drivers/scsi/ncr53c8xx.h
--- linux-2.5.64-bk4/drivers/scsi/ncr53c8xx.h	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk5/drivers/scsi/ncr53c8xx.h	Mon Mar 31 12:27:44 2003
@@ -60,17 +60,12 @@
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int ncr53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *);
-#else
-#define ncr53c8xx_release NULL
-#endif
 
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define NCR53C8XX {     .name           = "",			\
+#define NCR53C8XX {     .name           = "ncr53c8xx",		\
 			.detect         = ncr53c8xx_detect,	\
 			.release        = ncr53c8xx_release,	\
 			.info           = ncr53c8xx_info, 	\
diff -urN linux-2.5.64-bk4/drivers/scsi/pcmcia/Kconfig linux-2.5.64-bk5/drivers/scsi/pcmcia/Kconfig
--- linux-2.5.64-bk4/drivers/scsi/pcmcia/Kconfig	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk5/drivers/scsi/pcmcia/Kconfig	Mon Mar 31 12:27:44 2003
@@ -3,22 +3,11 @@
 #
 
 menu "PCMCIA SCSI adapter support"
-	depends on SCSI!=n && HOTPLUG && PCMCIA!=n
-
-config SCSI_PCMCIA
-	bool "PCMCIA SCSI adapter support"
-	help
-	  Say Y here if you intend to attach a PCMCIA or CardBus card to your
-	  computer which acts as a SCSI host adapter. These are credit card
-	  size devices often used with laptops.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions PCMCIA SCSI host adapters.
+	depends on SCSI!=n && PCMCIA!=n
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -30,7 +19,7 @@
 
 config PCMCIA_FDOMAIN
 	tristate "Future Domain PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -42,7 +31,7 @@
 
 config PCMCIA_NINJA_SCSI
 	tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  If you intend to attach this type of PCMCIA SCSI host adapter to
 	  your computer, say Y here and read
@@ -55,7 +44,7 @@
 
 config PCMCIA_QLOGIC
 	tristate "Qlogic PCMCIA support"
-	depends on SCSI_PCMCIA && m
+	depends on m
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
 	  adapter to your computer.
@@ -65,10 +54,4 @@
 	  whenever you want).  If you want to compile it as a module, say M
 	  here and read <file:Documentation/modules.txt>.
 
-config PCMCIA_SCSICARD
-	bool
-	depends on PCMCIA_QLOGIC=y || PCMCIA_AHA152X=y || PCMCIA_FDOMAIN=y || PCMCIA_NINJA_SCSI=y
-	default y
-
 endmenu
-
diff -urN linux-2.5.64-bk4/drivers/scsi/pcmcia/fdomain_stub.c linux-2.5.64-bk5/drivers/scsi/pcmcia/fdomain_stub.c
--- linux-2.5.64-bk4/drivers/scsi/pcmcia/fdomain_stub.c	Tue Mar  4 19:29:23 2003
+++ linux-2.5.64-bk5/drivers/scsi/pcmcia/fdomain_stub.c	Mon Mar 31 12:27:44 2003
@@ -61,15 +61,15 @@
 MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
 MODULE_LICENSE("Dual MPL/GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
-
 /* Bit map of interrupts to choose from */
-INT_MODULE_PARM(irq_mask, 0xdeb8);
+static int irq_mask = 0xdeb8;
+MODULE_PARM(irq_mask, "i");
 static int irq_list[4] = { -1 };
 MODULE_PARM(irq_list, "1-4i");
 
 #ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
 "fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
@@ -81,11 +81,15 @@
 
 typedef struct scsi_info_t {
     dev_link_t		link;
+    struct Scsi_Host	*host;
     int			ndev;
     dev_node_t		node[8];
 } scsi_info_t;
 
+extern Scsi_Host_Template fdomain_driver_template;
 extern void fdomain_setup(char *str, int *ints);
+extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt );
+extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
 
 static void fdomain_release(u_long arg);
 static int fdomain_event(event_t event, int priority,
@@ -94,8 +98,6 @@
 static dev_link_t *fdomain_attach(void);
 static void fdomain_detach(dev_link_t *);
 
-#define driver_template fdomain_driver_template
-extern Scsi_Host_Template fdomain_driver_template;
 
 static dev_link_t *dev_list = NULL;
 
@@ -231,7 +233,6 @@
     link->conf.ConfigBase = parse.config.base;
 
     /* Configure card */
-    driver_template.module = &__this_module;
     link->state |= DEV_CONFIG;
     
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -260,14 +261,18 @@
     sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
     fdomain_setup(str, ints);
     
-    scsi_register_host(&driver_template);
+    host = __fdomain_16x0_detect(&fdomain_driver_template);
+    if (!host) {
+        printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+	goto cs_failed;
+    }
+ 
+    scsi_add_host(host, NULL);
 
     tail = &link->dev;
     info->ndev = 0;
-    for (host = scsi_host_get_next(NULL); host;
-	 host = scsi_host_get_next(host))
-	if (host->hostt == &driver_template)
-	    list_for_each_entry (dev, &host->my_devices, siblings) {
+   
+    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
@@ -296,10 +301,11 @@
 	    }
 	    *tail = node; tail = &node->next;
 	    info->ndev++;
-	}
+
+    }
+
     *tail = NULL;
-    if (info->ndev == 0)
-	printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
+    info->host = host;
     
     link->state &= ~DEV_CONFIG_PENDING;
     return;
@@ -316,30 +322,22 @@
 static void fdomain_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
+    scsi_info_t *info = link->priv;
 
     DEBUG(0, "fdomain_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-    if (GET_USE_COUNT(&__this_module) != 0) {
-	DEBUG(1, "fdomain_cs: release postponed, "
-	      "device still open\n");
-	link->state |= DEV_STALE_CONFIG;
-	return;
-    }
-#endif
-
-    scsi_unregister_host(&driver_template);
+    scsi_remove_host(info->host);
     link->dev = NULL;
     
     CardServices(ReleaseConfiguration, link->handle);
     CardServices(ReleaseIO, link->handle, &link->io);
     CardServices(ReleaseIRQ, link->handle, &link->irq);
-    
+
+    scsi_unregister(info->host);
+
     link->state &= ~DEV_CONFIG;
     if (link->state & DEV_STALE_LINK)
 	fdomain_detach(link);
-    
 } /* fdomain_release */
 
 /*====================================================================*/
@@ -374,7 +372,7 @@
     case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
 	    CardServices(RequestConfiguration, link->handle, &link->conf);
-	    fdomain_16x0_reset(NULL, 0);
+	    fdomain_16x0_bus_reset(NULL);
 	}
 	break;
     }
diff -urN linux-2.5.64-bk4/drivers/scsi/pcmcia/qlogic_stub.c linux-2.5.64-bk5/drivers/scsi/pcmcia/qlogic_stub.c
--- linux-2.5.64-bk4/drivers/scsi/pcmcia/qlogic_stub.c	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk5/drivers/scsi/pcmcia/qlogic_stub.c	Mon Mar 31 12:27:44 2003
@@ -55,7 +55,11 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
 
+
+extern Scsi_Host_Template qlogicfas_driver_template;
 extern void qlogicfas_preset(int port, int irq);
+extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *);
+extern int qlogicfas_bus_reset(Scsi_Cmnd *);
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
@@ -81,6 +85,7 @@
 
 typedef struct scsi_info_t {
 	dev_link_t link;
+	struct Scsi_Host *host;
 	unsigned short manf_id;
 	int ndev;
 	dev_node_t node[8];
@@ -92,9 +97,6 @@
 static dev_link_t *qlogic_attach(void);
 static void qlogic_detach(dev_link_t *);
 
-/* Import our driver template */
-extern Scsi_Host_Template qlogicfas_driver_template;
-#define driver_template qlogicfas_driver_template
 
 static dev_link_t *dev_list = NULL;
 
@@ -233,7 +235,6 @@
 		info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
 	/* Configure card */
-	driver_template.module = &__this_module;
 	link->state |= DEV_CONFIG;
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
@@ -272,46 +273,52 @@
 	else
 		qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ);
 
-	scsi_register_host(&driver_template);
-
 	tail = &link->dev;
 	info->ndev = 0;
-	for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host))
-		if (host->hostt == &driver_template)
-			list_for_each_entry (dev, &host->my_devices, siblings) {
-				u_long arg[2], id;
-				kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
-				id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
-				node = &info->node[info->ndev];
-				node->minor = 0;
-				switch (dev->type) {
-				case TYPE_TAPE:
-					node->major = SCSI_TAPE_MAJOR;
-					sprintf(node->dev_name, "st#%04lx", id);
-					break;
-				case TYPE_DISK:
-				case TYPE_MOD:
-					node->major = SCSI_DISK0_MAJOR;
-					sprintf(node->dev_name, "sd#%04lx", id);
-					break;
-				case TYPE_ROM:
-				case TYPE_WORM:
-					node->major = SCSI_CDROM_MAJOR;
-					sprintf(node->dev_name, "sr#%04lx", id);
-					break;
-				default:
-					node->major = SCSI_GENERIC_MAJOR;
-					sprintf(node->dev_name, "sg#%04lx", id);
-					break;
-				}
-				*tail = node;
-				tail = &node->next;
-				info->ndev++;
-			}
-	*tail = NULL;
-	if (info->ndev == 0)
+
+	host = __qlogicfas_detect(&qlogicfas_driver_template);
+	if (!host) {
 		printk(KERN_INFO "qlogic_cs: no SCSI devices found\n");
+		goto out;
+	}
+
+	scsi_add_host(host, NULL);
+
+	list_for_each_entry(dev, &host->my_devices, siblings) {
+		u_long arg[2], id;
+		kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
+		id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000);
+		node = &info->node[info->ndev];
+		node->minor = 0;
+		switch (dev->type) {
+		case TYPE_TAPE:
+			node->major = SCSI_TAPE_MAJOR;
+			sprintf(node->dev_name, "st#%04lx", id);
+			break;
+		case TYPE_DISK:
+		case TYPE_MOD:
+			node->major = SCSI_DISK0_MAJOR;
+			sprintf(node->dev_name, "sd#%04lx", id);
+			break;
+		case TYPE_ROM:
+		case TYPE_WORM:
+			node->major = SCSI_CDROM_MAJOR;
+			sprintf(node->dev_name, "sr#%04lx", id);
+			break;
+		default:
+			node->major = SCSI_GENERIC_MAJOR;
+			sprintf(node->dev_name, "sg#%04lx", id);
+			break;
+		}
+		*tail = node;
+		tail = &node->next;
+		info->ndev++;
+	}
 
+	*tail = NULL;
+	info->host = host;
+
+out:
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
 
@@ -327,29 +334,22 @@
 static void qlogic_release(u_long arg)
 {
 	dev_link_t *link = (dev_link_t *) arg;
+	scsi_info_t *info = link->priv;
 
 	DEBUG(0, "qlogic_release(0x%p)\n", link);
 
-#warning This does not protect you.  You need some real fix for your races.
-#if 0
-	if (GET_USE_COUNT(&__this_module) != 0) {
-		DEBUG(0, "qlogic_cs: release postponed, device still open\n");
-		link->state |= DEV_STALE_CONFIG;
-		return;
-	}
-#endif
-
-	scsi_unregister_host(&driver_template);
+	scsi_remove_host(info->host);
 	link->dev = NULL;
 
 	CardServices(ReleaseConfiguration, link->handle);
 	CardServices(ReleaseIO, link->handle, &link->io);
 	CardServices(ReleaseIRQ, link->handle, &link->irq);
 
+	scsi_unregister(info->host);
+
 	link->state &= ~DEV_CONFIG;
 	if (link->state & DEV_STALE_LINK)
 		qlogic_detach(link);
-
 }				/* qlogic_release */
 
 /*====================================================================*/
@@ -390,7 +390,7 @@
 				outb(0x04, link->io.BasePort1 + 0xd);
 			}
 			/* Ugggglllyyyy!!! */
-			driver_template.eh_bus_reset_handler(NULL);
+			qlogicfas_bus_reset(NULL);
 		}
 		break;
 	}
diff -urN linux-2.5.64-bk4/drivers/scsi/qlogicfas.c linux-2.5.64-bk5/drivers/scsi/qlogicfas.c
--- linux-2.5.64-bk4/drivers/scsi/qlogicfas.c	Tue Mar  4 19:29:55 2003
+++ linux-2.5.64-bk5/drivers/scsi/qlogicfas.c	Mon Mar 31 12:27:44 2003
@@ -127,11 +127,6 @@
 #endif
 
 #include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif
-
 #include <linux/blk.h>		/* to get disk capacity */
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -148,7 +143,6 @@
 
 #include "scsi.h"
 #include "hosts.h"
-#include "qlogicfas.h"
 
 /*----------------------------------------------------------------*/
 /* driver state info, local to driver */
@@ -166,6 +160,8 @@
 static int qlcfg9 = ((XTALFREQ + 4) / 5);
 static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4);
 
+int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
+
 /*----------------------------------------------------------------*/
 /* The qlogic card uses two register maps - These macros select which one */
 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
@@ -631,14 +627,12 @@
  *	Look for qlogic card and init if found 
  */
  
-int __devinit qlogicfas_detect(Scsi_Host_Template * host)
+struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host)
 {
 	int i, j;		/* these are only used by IRQ detect */
 	int qltyp;		/* type of chip */
 	struct Scsi_Host *hreg;	/* registered host structure */
 
-	host->proc_name = "qlogicfas";
-
 	/*	Qlogic Cards only exist at 0x230 or 0x330 (the chip itself
 	 *	decodes the address - I check 230 first since MIDI cards are
 	 *	typically at 0x330
@@ -659,7 +653,7 @@
 			release_region(qbase, 0x10);
 		}
 		if (qbase == 0x430)
-			return 0;
+			return NULL;;
 	} else
 		printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase);
 
@@ -726,16 +720,21 @@
 		qltyp, qbase, qlirq, QL_TURBO_PDMA);
 	host->name = qinfo;
 
-	return 1;
+	return hreg;
 
 err_release_mem:
 	release_region(qbase, 0x10);
 	if (host->can_queue)
 		free_irq(qlirq, do_ql_ihandl);
-	return 0;
+	return NULL;;
 
 }
 
+int __devinit qlogicfas_detect(Scsi_Host_Template *sht)
+{
+	return (__qlogicfas_detect(sht) != NULL);
+}
+
 /* 
  *	Return bios parameters 
  */
@@ -777,7 +776,7 @@
  *	the PCMCIA qlogic_stub code. This wants fixing
  */
 
-static int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
+int qlogicfas_bus_reset(Scsi_Cmnd * cmd)
 {
 	qabort = 2;
 	ql_zap();
@@ -818,9 +817,27 @@
 /*
  *	The driver template is also needed for PCMCIA
  */
- 
-Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS;
-#define driver_template qlogicfas_driver_template
+Scsi_Host_Template qlogicfas_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "qlogicfas",
+	.proc_name		= "qlogicfas",
+	.detect			= qlogicfas_detect,
+	.info			= qlogicfas_info,
+	.command		= qlogicfas_command,
+	.queuecommand		= qlogicfas_queuecommand,
+	.eh_abort_handler	= qlogicfas_abort,
+	.eh_bus_reset_handler	= qlogicfas_bus_reset,
+	.eh_device_reset_handler= qlogicfas_device_reset,
+	.eh_host_reset_handler	= qlogicfas_host_reset,
+	.bios_param		= qlogicfas_biosparam,
+	.can_queue		= 0,
+	.this_id		= -1,
+	.sg_tablesize		= SG_ALL,
+	.cmd_per_lun		= 1,
+	.use_clustering		= DISABLE_CLUSTERING,
+};
 
+#ifndef PCMCIA
+#define driver_template qlogicfas_driver_template
 #include "scsi_module.c"
-
+#endif
diff -urN linux-2.5.64-bk4/drivers/scsi/qlogicfas.h linux-2.5.64-bk5/drivers/scsi/qlogicfas.h
--- linux-2.5.64-bk4/drivers/scsi/qlogicfas.h	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk5/drivers/scsi/qlogicfas.h	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-#ifndef _QLOGICFAS_H
-#define _QLOGICFAS_H
-
-static int qlogicfas_detect(Scsi_Host_Template * );
-static const char * qlogicfas_info(struct Scsi_Host *);
-static int qlogicfas_command(Scsi_Cmnd *);
-static int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-static int qlogicfas_abort(Scsi_Cmnd *);
-static int qlogicfas_bus_reset(Scsi_Cmnd *);
-static int qlogicfas_device_reset(Scsi_Cmnd *);
-static int qlogicfas_host_reset(Scsi_Cmnd *);
-static int qlogicfas_biosparam(struct scsi_device *, struct block_device *,
-			       sector_t, int[]);
-
-#define QLOGICFAS {						\
-	.detect         		= qlogicfas_detect,	\
-	.info           		= qlogicfas_info,		\
-	.command     			= qlogicfas_command, 	\
-	.queuecommand			= qlogicfas_queuecommand,	\
-	.eh_abort_handler          	= qlogicfas_abort,	\
-	.eh_bus_reset_handler		= qlogicfas_bus_reset,	\
-	.eh_device_reset_handler        = qlogicfas_device_reset,	\
-	.eh_host_reset_handler          = qlogicfas_host_reset,	\
-	.bios_param     = qlogicfas_biosparam,			\
-	.can_queue      = 0,					\
-	.this_id        = -1,					\
-	.sg_tablesize   = SG_ALL,					\
-	.cmd_per_lun    = 1,					\
-	.use_clustering = DISABLE_CLUSTERING			\
-}
-#endif /* _QLOGICFAS_H */
-
-
-
diff -urN linux-2.5.64-bk4/drivers/scsi/scsi_error.c linux-2.5.64-bk5/drivers/scsi/scsi_error.c
--- linux-2.5.64-bk4/drivers/scsi/scsi_error.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/drivers/scsi/scsi_error.c	Mon Mar 31 12:27:44 2003
@@ -514,7 +514,7 @@
 	 * actually did complete normally.
 	 */
 	if (rtn == SUCCESS) {
-		int rtn = scsi_eh_completed_normally(scmd);
+		rtn = scsi_eh_completed_normally(scmd);
 		SCSI_LOG_ERROR_RECOVERY(3,
 			printk("%s: scsi_eh_completed_normally %x\n",
 			       __FUNCTION__, rtn));
@@ -544,20 +544,20 @@
 static int scsi_request_sense(struct scsi_cmnd *scmd)
 {
 	static unsigned char generic_sense[6] =
-	{REQUEST_SENSE, 0, 0, 0, 255, 0};
-	unsigned char scsi_result0[256], *scsi_result = &scsi_result0[0];
+	{REQUEST_SENSE, 0, 0, 0, 254, 0};
+	unsigned char *scsi_result;
 	int saved_result;
 	int rtn;
 
 	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
 
-	if (scmd->device->host->hostt->unchecked_isa_dma) {
-		scsi_result = kmalloc(512, GFP_ATOMIC | __GFP_DMA);
-		if (unlikely(!scsi_result)) {
-			printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
-					__FUNCTION__);
-			return FAILED;
-		}
+	scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0);
+
+
+	if (unlikely(!scsi_result)) {
+		printk(KERN_ERR "%s: cannot allocate scsi_result.\n",
+		       __FUNCTION__);
+		return FAILED;
 	}
 
 	/*
@@ -567,11 +567,11 @@
 	 * address (db).  0 is not a valid sense code. 
 	 */
 	memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
-	memset(scsi_result, 0, 256);
+	memset(scsi_result, 0, 254);
 
 	saved_result = scmd->result;
 	scmd->request_buffer = scsi_result;
-	scmd->request_bufflen = 256;
+	scmd->request_bufflen = 254;
 	scmd->use_sg = 0;
 	scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
 	scmd->sc_data_direction = SCSI_DATA_READ;
@@ -580,13 +580,12 @@
 	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT);
 
 	/* last chance to have valid sense data */
-	if (!SCSI_SENSE_VALID(scmd)) {
+	if(!SCSI_SENSE_VALID(scmd)) {
 		memcpy(scmd->sense_buffer, scmd->request_buffer,
-				sizeof(scmd->sense_buffer));
+		       sizeof(scmd->sense_buffer));
 	}
 
-	if (scsi_result != &scsi_result0[0])
-		kfree(scsi_result);
+	kfree(scsi_result);
 
 	/*
 	 * when we eventually call scsi_finish, we really wish to complete
@@ -702,25 +701,14 @@
 		 * upper level.
 		 */
 		if (rtn == SUCCESS)
-			scsi_eh_finish_cmd(scmd, done_q);
-		if (rtn != NEEDS_RETRY)
+			/* we don't want this command reissued, just
+			 * finished with the sense data, so set
+			 * retries to the max allowed to ensure it
+			 * won't get reissued */
+			scmd->retries = scmd->allowed;
+		else if (rtn != NEEDS_RETRY)
 			continue;
 
-		/*
-		 * we only come in here if we want to retry a
-		 * command.  the test to see whether the command
-		 * should be retried should be keeping track of the
-		 * number of tries, so we don't end up looping, of
-		 * course.
-		 */
-		scmd->state = NEEDS_RETRY;
-		rtn = scsi_eh_retry_cmd(scmd);
-		if (rtn != SUCCESS)
-			continue;
-
-		/*
-		 * we eventually hand this one back to the top level.
-		 */
 		scsi_eh_finish_cmd(scmd, done_q);
 	}
 
@@ -1322,9 +1310,11 @@
 		rtn = scsi_check_sense(scmd);
 		if (rtn == NEEDS_RETRY)
 			goto maybe_retry;
-		/* if rtn == FAILED, we have no sense information */
-		/* was: return rtn; */
-		return SUCCESS;
+		/* if rtn == FAILED, we have no sense information;
+		 * returning FAILED will wake the error handler thread
+		 * to collect the sense and redo the decide
+		 * disposition */
+		return rtn;
 	case CONDITION_GOOD:
 	case INTERMEDIATE_GOOD:
 	case INTERMEDIATE_C_GOOD:
diff -urN linux-2.5.64-bk4/drivers/scsi/scsi_lib.c linux-2.5.64-bk5/drivers/scsi/scsi_lib.c
--- linux-2.5.64-bk4/drivers/scsi/scsi_lib.c	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk5/drivers/scsi/scsi_lib.c	Mon Mar 31 12:27:44 2003
@@ -265,7 +265,6 @@
 	cmd->serial_number = 0;
 	cmd->serial_number_at_timeout = 0;
 	cmd->flags = 0;
-	cmd->retries = 0;
 	cmd->abort_reason = 0;
 
 	memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
diff -urN linux-2.5.64-bk4/drivers/scsi/sd.c linux-2.5.64-bk5/drivers/scsi/sd.c
--- linux-2.5.64-bk4/drivers/scsi/sd.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/drivers/scsi/sd.c	Mon Mar 31 12:27:44 2003
@@ -1197,7 +1197,7 @@
 		return;
 	}
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
 		printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation "
 		       "failure.\n");
diff -urN linux-2.5.64-bk4/drivers/scsi/sr.c linux-2.5.64-bk5/drivers/scsi/sr.c
--- linux-2.5.64-bk4/drivers/scsi/sr.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/drivers/scsi/sr.c	Mon Mar 31 12:27:44 2003
@@ -604,7 +604,7 @@
 	struct scsi_request *SRpnt = NULL;
 	request_queue_t *queue;
 
-	buffer = kmalloc(512, GFP_DMA);
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
 	if (!buffer)
 		goto Enomem;
 	SRpnt = scsi_allocate_request(cd->device);
@@ -698,7 +698,7 @@
 	goto out;
 }
 
-void get_capabilities(struct scsi_cd *cd)
+static void get_capabilities(struct scsi_cd *cd)
 {
 	struct cdrom_generic_command cgc;
 	unsigned char *buffer;
@@ -716,9 +716,8 @@
 		""
 	};
 
-	buffer = kmalloc(512, GFP_DMA);
-	if (!buffer)
-	{
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
 		printk(KERN_ERR "sr: out of memory.\n");
 		return;
 	}
diff -urN linux-2.5.64-bk4/drivers/scsi/sym53c8xx.c linux-2.5.64-bk5/drivers/scsi/sym53c8xx.c
--- linux-2.5.64-bk4/drivers/scsi/sym53c8xx.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk5/drivers/scsi/sym53c8xx.c	Mon Mar 31 12:27:44 2003
@@ -112,8 +112,8 @@
 #include <asm/spinlock.h>
 #endif
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -7214,7 +7214,6 @@
 **==========================================================
 */
 
-#ifdef MODULE
 static int ncr_detach(ncb_p np)
 {
 	int i;
@@ -7260,7 +7259,6 @@
 
 	return 1;
 }
-#endif
 
 /*==========================================================
 **
@@ -12958,6 +12956,7 @@
 		}
 		if (i != count)	/* Ignore this device if we already have it */
 			continue;
+		pci_set_master(pcidev);
 		devp = &devtbl[count];
 		devp->host_id = driver_setup.host_id;
 		devp->attach_done = 0;
@@ -13798,7 +13797,6 @@
 }
 
 
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *host)
 {
 #ifdef DEBUG_SYM53C8XX
@@ -13808,7 +13806,6 @@
 
      return 1;
 }
-#endif
 
 
 /*
diff -urN linux-2.5.64-bk4/drivers/scsi/sym53c8xx.h linux-2.5.64-bk5/drivers/scsi/sym53c8xx.h
--- linux-2.5.64-bk4/drivers/scsi/sym53c8xx.h	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk5/drivers/scsi/sym53c8xx.h	Mon Mar 31 12:27:44 2003
@@ -75,17 +75,11 @@
 int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int sym53c8xx_reset(Scsi_Cmnd *, unsigned int);
 int sym53c8xx_slave_configure(Scsi_Device *);
-
-#ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *);
-#else
-#define sym53c8xx_release NULL
-#endif
-
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
 
-#define SYM53C8XX {     .name           = "",			\
+#define SYM53C8XX {     .name           = "sym53c8xx",		\
 			.detect         = sym53c8xx_detect,	\
 			.release        = sym53c8xx_release,	\
 			.info           = sym53c8xx_info, 	\
diff -urN linux-2.5.64-bk4/drivers/scsi/zalon.c linux-2.5.64-bk5/drivers/scsi/zalon.c
--- linux-2.5.64-bk4/drivers/scsi/zalon.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk5/drivers/scsi/zalon.c	Mon Mar 31 12:27:44 2003
@@ -151,7 +151,6 @@
 	return (hosts_used != 0);
 }
 
-#ifdef MODULE
 extern int ncr53c8xx_release(struct Scsi_Host *host);
 
 int zalon7xx_release(struct Scsi_Host *host)
@@ -160,4 +159,3 @@
 	unregister_parisc_driver(&zalon_driver);
 	return 1;
 }
-#endif
diff -urN linux-2.5.64-bk4/drivers/scsi/zalon.h linux-2.5.64-bk5/drivers/scsi/zalon.h
--- linux-2.5.64-bk4/drivers/scsi/zalon.h	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk5/drivers/scsi/zalon.h	Mon Mar 31 12:27:44 2003
@@ -15,12 +15,7 @@
 int zalon7xx_detect(Scsi_Host_Template *tpnt);
 const char *ncr53c8xx_info(struct Scsi_Host *host);
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-
-#ifdef MODULE
 int zalon7xx_release(struct Scsi_Host *);
-#else
-#define zalon7xx_release NULL
-#endif
 
 #define GSC_SCSI_ZALON_OFFSET 0x800
 
diff -urN linux-2.5.64-bk4/include/asm-i386/i387.h linux-2.5.64-bk5/include/asm-i386/i387.h
--- linux-2.5.64-bk4/include/asm-i386/i387.h	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk5/include/asm-i386/i387.h	Mon Mar 31 12:27:44 2003
@@ -21,23 +21,41 @@
 /*
  * FPU lazy state save handling...
  */
-extern void save_init_fpu( struct task_struct *tsk );
 extern void restore_fpu( struct task_struct *tsk );
 
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
 
+static inline void __save_init_fpu( struct task_struct *tsk )
+{
+	if ( cpu_has_fxsr ) {
+		asm volatile( "fxsave %0 ; fnclex"
+			      : "=m" (tsk->thread.i387.fxsave) );
+	} else {
+		asm volatile( "fnsave %0 ; fwait"
+			      : "=m" (tsk->thread.i387.fsave) );
+	}
+	tsk->thread_info->flags &= ~_TIF_USEDFPU;
+}
+
+static inline void save_init_fpu( struct task_struct *tsk )
+{
+	__save_init_fpu(tsk);
+	stts();
+}
+
+
 #define unlazy_fpu( tsk ) do { \
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) \
+	if ((tsk)->thread_info->flags & _TIF_USEDFPU) \
 		save_init_fpu( tsk ); \
 } while (0)
 
 #define clear_fpu( tsk )					\
 do {								\
-	if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) {		\
+	if ((tsk)->thread_info->flags & _TIF_USEDFPU) {		\
 		asm volatile("fwait");				\
-		clear_tsk_thread_flag(tsk, TIF_USEDFPU);	\
+		(tsk)->thread_info->flags &= ~_TIF_USEDFPU;	\
 		stts();						\
 	}							\
 } while (0)
diff -urN linux-2.5.64-bk4/include/asm-i386/processor.h linux-2.5.64-bk5/include/asm-i386/processor.h
--- linux-2.5.64-bk4/include/asm-i386/processor.h	Tue Mar  4 19:28:56 2003
+++ linux-2.5.64-bk5/include/asm-i386/processor.h	Mon Mar 31 12:27:44 2003
@@ -347,7 +347,7 @@
 	unsigned long	esp0;
 	unsigned short	ss0,__ss0h;
 	unsigned long	esp1;
-	unsigned short	ss1,__ss1h;
+	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
 	unsigned long	esp2;
 	unsigned short	ss2,__ss2h;
 	unsigned long	__cr3;
@@ -413,15 +413,20 @@
 {
 	tss->esp0 = esp0;
 	if (cpu_has_sep) {
-		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+		if (tss->ss1 != __KERNEL_CS) {
+			tss->ss1 = __KERNEL_CS;
+			wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+		}
 		wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0);
 	}
 }
 
-static inline void disable_sysenter(void)
+static inline void disable_sysenter(struct tss_struct *tss)
 {
-	if (cpu_has_sep)  
+	if (cpu_has_sep)  {
+		tss->ss1 = 0;
 		wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+	}
 }
 
 #define start_thread(regs, new_eip, new_esp) do {		\
diff -urN linux-2.5.64-bk4/include/linux/cpufreq.h linux-2.5.64-bk5/include/linux/cpufreq.h
--- linux-2.5.64-bk4/include/linux/cpufreq.h	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk5/include/linux/cpufreq.h	Mon Mar 31 12:27:44 2003
@@ -18,7 +18,8 @@
 #include <linux/notifier.h>
 #include <linux/threads.h>
 #include <linux/device.h>
-
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
 
 #define CPUFREQ_NAME_LEN 16
 
@@ -69,6 +70,8 @@
 	struct cpufreq_cpuinfo  cpuinfo;     /* see above */
 	struct device		* dev;
 	struct kobject		kobj;
+ 	struct semaphore	lock;   /* CPU ->setpolicy or ->target may
+					   only be called once a time */
 };
 
 #define CPUFREQ_ADJUST          (0)
@@ -131,18 +134,13 @@
 };
 
 /* pass a target to the cpufreq driver 
- * _l : (cpufreq_driver_sem is not held)
  */
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation);
-
 /* pass an event to the cpufreq governor */
-int cpufreq_governor_l(unsigned int cpu, unsigned int event);
+int cpufreq_governor(unsigned int cpu, unsigned int event);
 
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
@@ -154,6 +152,8 @@
 #define CPUFREQ_RELATION_L 0  /* lowest frequency at or above target */
 #define CPUFREQ_RELATION_H 1  /* highest frequency below or at target */
 
+struct freq_attr;
+
 struct cpufreq_driver {
 	/* needed by all drivers */
 	int	(*verify)	(struct cpufreq_policy *policy);
@@ -164,16 +164,15 @@
 	int	(*target)	(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation);
+	struct module           *owner;
 	/* optional, for the moment */
 	int	(*init)		(struct cpufreq_policy *policy);
 	int	(*exit)		(struct cpufreq_policy *policy);
+	struct freq_attr	**attr;
 };
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
-/* deprecated */
-#define cpufreq_register(x)   cpufreq_register_driver(x)
-#define cpufreq_unregister() cpufreq_unregister_driver(NULL)
 
 
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
@@ -194,6 +193,13 @@
 	return;
 }
 
+struct freq_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct cpufreq_policy *, char *);
+	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
+};
+
+
 /*********************************************************************
  *                        CPUFREQ 2.6. INTERFACE                     *
  *********************************************************************/
@@ -289,16 +295,21 @@
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table);
 
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index);
-
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 				   struct cpufreq_frequency_table *table,
 				   unsigned int target_freq,
 				   unsigned int relation,
 				   unsigned int *index);
 
+/* the following are really really optional */
+extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+
+void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, 
+				      unsigned int cpu);
+
+void cpufreq_frequency_table_put_attr(unsigned int cpu);
+
+
 #endif /* CONFIG_CPU_FREQ_TABLE */
 
 #endif /* _LINUX_CPUFREQ_H */
diff -urN linux-2.5.64-bk4/include/linux/pci_ids.h linux-2.5.64-bk5/include/linux/pci_ids.h
--- linux-2.5.64-bk4/include/linux/pci_ids.h	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk5/include/linux/pci_ids.h	Mon Mar 31 12:27:44 2003
@@ -1854,6 +1854,7 @@
 #define PCI_DEVICE_ID_INTEL_82801DB_7	0x24c7
 #define PCI_DEVICE_ID_INTEL_82801DB_9	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_11	PCI_DEVICE_ID_INTEL_82801DB_9
+#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
 #define PCI_DEVICE_ID_INTEL_82801DB_13	0x24cd
 #define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
diff -urN linux-2.5.64-bk4/kernel/cpufreq.c linux-2.5.64-bk5/kernel/cpufreq.c
--- linux-2.5.64-bk4/kernel/cpufreq.c	Mon Mar 31 12:27:36 2003
+++ linux-2.5.64-bk5/kernel/cpufreq.c	Mon Mar 31 12:27:44 2003
@@ -43,12 +43,40 @@
  */
 static struct notifier_block    *cpufreq_policy_notifier_list;
 static struct notifier_block    *cpufreq_transition_notifier_list;
-static DECLARE_MUTEX            (cpufreq_notifier_sem);
+static DECLARE_RWSEM		(cpufreq_notifier_rwsem);
 
 
 LIST_HEAD(cpufreq_governor_list);
+static DECLARE_MUTEX		(cpufreq_governor_sem);
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event);
+static struct device_interface cpufreq_interface;
+
+static int cpufreq_cpu_get(unsigned int cpu) {
+	if (cpu >= NR_CPUS)
+		return 0;
+
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		module_put(cpufreq_driver->owner);
+		kset_put(&cpufreq_interface.kset);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void cpufreq_cpu_put(unsigned int cpu) {
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
+}
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -67,19 +95,19 @@
 		return 0;
 	} else 	{
 		struct cpufreq_governor *t;
-		down(&cpufreq_driver_sem);
+		down(&cpufreq_governor_sem);
 		if (!cpufreq_driver || !cpufreq_driver->target)
 			goto out;
 		list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 			if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
 				*governor = t;
 				*policy = CPUFREQ_POLICY_GOVERNOR;
-				up(&cpufreq_driver_sem);
+				up(&cpufreq_governor_sem);
 				return 0;
 			}
 		}
 	out:
-		up(&cpufreq_driver_sem);
+		up(&cpufreq_governor_sem);
 	}
 	return -EINVAL;
 }
@@ -120,14 +148,7 @@
 static ssize_t show_##file_name 					\
 (struct cpufreq_policy * policy, char *buf)				\
 {									\
-	unsigned int value = 0;						\
-									\
-	down(&cpufreq_driver_sem);					\
-	if (cpufreq_driver)						\
-		value = policy->object;					\
-	up(&cpufreq_driver_sem);					\
-									\
-	return sprintf (buf, "%u\n", value);				\
+	return sprintf (buf, "%u\n", policy->object);			\
 }
 
 show_one(cpuinfo_min_freq, cpuinfo.min_freq);
@@ -143,12 +164,17 @@
 (struct cpufreq_policy * policy, const char *buf, size_t count)		\
 {									\
 	unsigned int ret = -EINVAL;					\
+	struct cpufreq_policy new_policy;				\
 									\
-	ret = sscanf (buf, "%u", &policy->object);			\
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);		\
+	if (ret)							\
+		return -EINVAL;						\
+									\
+	ret = sscanf (buf, "%u", &new_policy.object);			\
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
-	ret = cpufreq_set_policy(policy);				\
+	ret = cpufreq_set_policy(&new_policy);				\
 									\
 	return ret ? ret : count;					\
 }
@@ -161,26 +187,16 @@
  */
 static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf)
 {
-	unsigned int value = 0;
-	char value2[CPUFREQ_NAME_LEN];
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		value = policy->policy;
-	if (value == CPUFREQ_POLICY_GOVERNOR)
-		strncpy(value2, policy->governor->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	switch (value) {
+	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE:
 		return sprintf(buf, "powersave\n");
 	case CPUFREQ_POLICY_PERFORMANCE:
 		return sprintf(buf, "performance\n");
 	case CPUFREQ_POLICY_GOVERNOR:
-		return sprintf(buf, "%s\n", value2);
+		return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name);
+	default:
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 
@@ -192,25 +208,55 @@
 {
 	unsigned int ret = -EINVAL;
 	char	str_governor[16];
+	struct cpufreq_policy new_policy;
+
+	ret = cpufreq_get_policy(&new_policy, policy->cpu);
+	if (ret)
+		return ret;
 
 	ret = sscanf (buf, "%15s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
 
-	if (cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor))
+	if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
 		return -EINVAL;
 
-	ret = cpufreq_set_policy(policy);
+	ret = cpufreq_set_policy(&new_policy);
 
 	return ret ? ret : count;
 }
 
+/**
+ * show_scaling_driver - show the cpufreq driver currently loaded
+ */
+static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf)
+{
+	return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+}
+
+/**
+ * show_scaling_available_governors - show the available CPUfreq governors
+ */
+static ssize_t show_scaling_available_governors(struct cpufreq_policy * policy, char *buf)
+{
+	ssize_t i = 0;
+	struct cpufreq_governor *t;
+
+	i += sprintf(buf, "performance powersave");
+
+	if (!cpufreq_driver->target)
+		goto out;
+
+	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
+		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
+			goto out;
+		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
+	}
+ out:
+	i += sprintf(&buf[i], "\n");
+	return i;
+}
 
-struct freq_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct cpufreq_policy *, char *);
-	ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
-};
 
 #define define_one_ro(_name) \
 struct freq_attr _name = { \
@@ -227,6 +273,8 @@
 
 define_one_ro(cpuinfo_min_freq);
 define_one_ro(cpuinfo_max_freq);
+define_one_ro(scaling_available_governors);
+define_one_ro(scaling_driver);
 define_one_rw(scaling_min_freq);
 define_one_rw(scaling_max_freq);
 define_one_rw(scaling_governor);
@@ -237,10 +285,11 @@
 	&scaling_min_freq.attr,
 	&scaling_max_freq.attr,
 	&scaling_governor.attr,
+	&scaling_driver.attr,
+	&scaling_available_governors.attr,
 	NULL
 };
 
-
 #define to_policy(k) container_of(k,struct cpufreq_policy,kobj)
 #define to_attr(a) container_of(a,struct freq_attr,attr)
 
@@ -248,7 +297,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->show ? fattr->show(policy,buf) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->show ? fattr->show(policy,buf) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static ssize_t store(struct kobject * kobj, struct attribute * attr, 
@@ -256,7 +310,12 @@
 {
 	struct cpufreq_policy * policy = to_policy(kobj);
 	struct freq_attr * fattr = to_attr(attr);
-	return fattr->store ? fattr->store(policy,buf,count) : 0;
+	ssize_t ret;
+	if (!cpufreq_cpu_get(policy->cpu))
+		return -EINVAL;
+	ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+	cpufreq_cpu_put(policy->cpu);
+	return ret;
 }
 
 static struct sysfs_ops sysfs_ops = {
@@ -271,56 +330,6 @@
 
 
 /**
- * show_scaling_governor - show the current policy for the specified CPU
- */
-static ssize_t show_scaling_driver (struct device *dev, char *buf)
-{
-	char value[CPUFREQ_NAME_LEN];
-
-	if (!dev)
-		return 0;
-
-	down(&cpufreq_driver_sem);
-	if (cpufreq_driver)
-		strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
-	up(&cpufreq_driver_sem);
-
-	return sprintf(buf, "%s\n", value);
-}
-
-/**
- * show_available_govs - show the available CPUfreq governors
- */
-static ssize_t show_available_govs(struct device *dev, char *buf)
-{
-	ssize_t i = 0;
-	struct cpufreq_governor *t;
-
-	if (!dev)
-		return 0;
-
-	i += sprintf(buf, "performance powersave");
-
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !cpufreq_driver->target)
-		goto out;
-
-	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2)))
-			goto out;
-		i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name);
-	}
- out:
-	up(&cpufreq_driver_sem);
-	i += sprintf(&buf[i], "\n");
-	return i;
-}
-
-
-static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
-static DEVICE_ATTR(available_scaling_governors, S_IRUGO, show_available_govs, NULL);
-
-/**
  * cpufreq_add_dev - add a CPU device
  *
  * Adds the cpufreq interface for a CPU device. 
@@ -329,57 +338,62 @@
 {
 	unsigned int cpu = to_cpu_nr(dev);
 	int ret = 0;
-	struct cpufreq_policy policy;
+	struct cpufreq_policy new_policy;
+	struct cpufreq_policy *policy;
+	struct freq_attr **drv_attr;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver) {
-		up(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!try_module_get(cpufreq_driver->owner)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
 	/* call driver. From then on the cpufreq must be able
 	 * to accept all calls to ->verify and ->setpolicy for this CPU
 	 */
-	cpufreq_driver->policy[cpu].cpu = cpu;
+	policy = &cpufreq_driver->policy[cpu];
+	policy->cpu = cpu;
 	if (cpufreq_driver->init) {
-		ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]);
-		if (ret) {
-			up(&cpufreq_driver_sem);
-			return -ENODEV;
-		}
+		ret = cpufreq_driver->init(policy);
+		if (ret)
+			goto out;
 	}
 
 	/* set default policy on this CPU */
-	memcpy(&policy, 
-	       &cpufreq_driver->policy[cpu], 
+	down(&cpufreq_driver_sem);
+	memcpy(&new_policy, 
+	       policy, 
 	       sizeof(struct cpufreq_policy));
-
-	/* 2.4-API init for this CPU */
-#ifdef CONFIG_CPU_FREQ_24_API
-	cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
-	cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
-	cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
-#endif
-
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_START);
-
 	up(&cpufreq_driver_sem);
-	ret = cpufreq_set_policy(&policy);
-	if (ret)
-		return -EINVAL;
-	down(&cpufreq_driver_sem);
 
+	init_MUTEX(&policy->lock);
 	/* prepare interface data */
-	policy.kobj.parent = &dev->kobj;
-	policy.kobj.ktype = &ktype_cpufreq;
-	policy.dev = dev;
-	strncpy(policy.kobj.name, 
+	policy->kobj.parent = &dev->kobj;
+	policy->kobj.ktype = &ktype_cpufreq;
+	policy->dev = dev;
+	strncpy(policy->kobj.name, 
 		cpufreq_interface.name, KOBJ_NAME_LEN);
 
-	ret = kobject_register(&policy.kobj);
+	ret = kobject_register(&policy->kobj);
+	if (ret)
+		goto out;
+
+	drv_attr = cpufreq_driver->attr;
+	while ((drv_attr) && (*drv_attr)) {
+		sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+		drv_attr++;
+	}
 
-	up(&cpufreq_driver_sem);
+	/* set default policy */
+	ret = cpufreq_set_policy(&new_policy);
+	if (ret)
+		kobject_unregister(&policy->kobj);
+
+ out:
+	module_put(cpufreq_driver->owner);
+	kset_put(&cpufreq_interface.kset);
 	return ret;
 }
 
@@ -387,21 +401,39 @@
 /**
  * cpufreq_remove_dev - remove a CPU device
  *
- * Removes the cpufreq interface for a CPU device. Is called with
- * cpufreq_driver_sem locked.
+ * Removes the cpufreq interface for a CPU device.
  */
 static int cpufreq_remove_dev (struct device * dev)
 {
 	unsigned int cpu = to_cpu_nr(dev);
 
-	if (cpufreq_driver->target)
-		cpufreq_governor(cpu, CPUFREQ_GOV_STOP);
+	if (!kset_get(&cpufreq_interface.kset))
+		return -EINVAL;
+
+	if (!kobject_get(&cpufreq_driver->policy[cpu].kobj)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EINVAL;
+	}
 
+	down(&cpufreq_driver_sem);
+	if ((cpufreq_driver->target) && 
+	    (cpufreq_driver->policy[cpu].policy == CPUFREQ_POLICY_GOVERNOR)) {
+		cpufreq_driver->policy[cpu].governor->governor(&cpufreq_driver->policy[cpu], CPUFREQ_GOV_STOP);
+		module_put(cpufreq_driver->policy[cpu].governor->owner);
+	}
+
+	/* we may call driver->exit here without checking for try_module_exit
+	 * as it's either the driver which wants to unload or we have a CPU
+	 * removal AND driver removal at the same time...
+	 */
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(&cpufreq_driver->policy[cpu]);
 
 	kobject_unregister(&cpufreq_driver->policy[cpu].kobj);
 
+	up(&cpufreq_driver_sem);
+	kobject_put(&cpufreq_driver->policy[cpu].kobj);
+	kset_put(&cpufreq_interface.kset);
 	return 0;
 }
 
@@ -427,7 +459,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb);
@@ -438,7 +470,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -459,7 +491,7 @@
 {
 	int ret;
 
-	down(&cpufreq_notifier_sem);
+	down_write(&cpufreq_notifier_rwsem);
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
 		ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb);
@@ -470,7 +502,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&cpufreq_notifier_sem);
+	up_write(&cpufreq_notifier_rwsem);
 
 	return ret;
 }
@@ -481,71 +513,72 @@
  *                              GOVERNORS                            *
  *********************************************************************/
 
-inline int cpufreq_driver_target_l(struct cpufreq_policy *policy,
-				   unsigned int target_freq,
-				   unsigned int relation)
-{
-	unsigned int ret;
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver)
-		ret = -EINVAL;
-	else
-		ret = cpufreq_driver->target(policy, target_freq, relation);
-	up(&cpufreq_driver_sem);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(cpufreq_driver_target_l);
-
-
 inline int cpufreq_driver_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation)
 {
-	return cpufreq_driver->target(policy, target_freq, relation);
+	unsigned int ret;
+	unsigned int cpu = policy->cpu;
+
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
+	down(&cpufreq_driver->policy[cpu].lock);
+
+	ret = cpufreq_driver->target(policy, target_freq, relation);
+
+	up(&cpufreq_driver->policy[cpu].lock);
+
+	cpufreq_cpu_put(cpu);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
 
-static int cpufreq_governor(unsigned int cpu, unsigned int event)
+int cpufreq_governor(unsigned int cpu, unsigned int event)
 {
 	int ret = 0;
 	struct cpufreq_policy *policy = &cpufreq_driver->policy[cpu];
 
+	if (!cpufreq_cpu_get(cpu))
+		return -EINVAL;
+
 	switch (policy->policy) {
 	case CPUFREQ_POLICY_POWERSAVE: 
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->min, CPUFREQ_RELATION_L);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_PERFORMANCE:
-		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START))
+		if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) {
+			down(&cpufreq_driver->policy[cpu].lock);
 			ret = cpufreq_driver->target(policy, policy->max, CPUFREQ_RELATION_H);
+			up(&cpufreq_driver->policy[cpu].lock);
+		}
 		break;
 	case CPUFREQ_POLICY_GOVERNOR:
 		ret = -EINVAL;
-		if (event == CPUFREQ_GOV_START)
-			if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
-				break;
+		if (!try_module_get(cpufreq_driver->policy[cpu].governor->owner))
+			break;
 		ret = cpufreq_driver->policy[cpu].governor->governor(policy, event);
-		if ((event == CPUFREQ_GOV_STOP) ||
-			(ret && (event == CPUFREQ_GOV_START)))
+		/* we keep one module reference alive for each CPU governed by this CPU */
+		if ((event != CPUFREQ_GOV_START) || ret)
+			module_put(cpufreq_driver->policy[cpu].governor->owner);
+		if ((event == CPUFREQ_GOV_STOP) && !ret)
 			module_put(cpufreq_driver->policy[cpu].governor->owner);
 		break;
 	default:
 		ret = -EINVAL;
 	}
-	return ret;
-}
 
+	cpufreq_cpu_put(cpu);
 
-int cpufreq_governor_l(unsigned int cpu, unsigned int event)
-{
-	int ret = 0;
-	down(&cpufreq_driver_sem);
-	ret = cpufreq_governor(cpu, event);
-	up(&cpufreq_driver_sem);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_governor_l);
+EXPORT_SYMBOL_GPL(cpufreq_governor);
 
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
@@ -560,16 +593,17 @@
 	if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN))
 		return -EBUSY;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
 	
 	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
 		if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-			up(&cpufreq_driver_sem);
+			up(&cpufreq_governor_sem);
 			return -EBUSY;
 		}
 	}
 	list_add(&governor->governor_list, &cpufreq_governor_list);
- 	up(&cpufreq_driver_sem);
+
+ 	up(&cpufreq_governor_sem);
 
 	return 0;
 }
@@ -583,7 +617,8 @@
 	if (!governor)
 		return;
 
-	down(&cpufreq_driver_sem);
+	down(&cpufreq_governor_sem);
+
 	/* 
 	 * Unless the user uses rmmod -f, we can be safe. But we never
 	 * know, so check whether if it's currently used. If so,
@@ -591,17 +626,21 @@
 	 */
 	for (i=0; i<NR_CPUS; i++)
 	{
-		if (cpufreq_driver && 
-		    (cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
+		if (!cpufreq_cpu_get(i))
+			continue;
+		if ((cpufreq_driver->policy[i].policy == CPUFREQ_POLICY_GOVERNOR) && 
 		    (cpufreq_driver->policy[i].governor == governor)) {
 			cpufreq_governor(i, CPUFREQ_GOV_STOP);
 			cpufreq_driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
 			cpufreq_governor(i, CPUFREQ_GOV_START);
+			cpufreq_governor(i, CPUFREQ_GOV_LIMITS);
 		}
+		cpufreq_cpu_put(i);
 	}
+
 	/* now we can safely remove it from the list */
 	list_del(&governor->governor_list);
-	up(&cpufreq_driver_sem);
+	up(&cpufreq_governor_sem);
 	return;
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
@@ -620,19 +659,17 @@
  */
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 {
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver  || !policy || 
-	    (cpu >= NR_CPUS) || (!cpu_online(cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(policy, 
 	       &cpufreq_driver->policy[cpu], 
 	       sizeof(struct cpufreq_policy));
-	
 	up(&cpufreq_driver_sem);
 
+	cpufreq_cpu_put(cpu);
+
 	return 0;
 }
 EXPORT_SYMBOL(cpufreq_get_policy);
@@ -646,27 +683,23 @@
  */
 int cpufreq_set_policy(struct cpufreq_policy *policy)
 {
-	int ret;
+	int ret = 0;
 
-	down(&cpufreq_driver_sem);
-	if (!cpufreq_driver || !policy ||
-	    (policy->cpu >= NR_CPUS) || (!cpu_online(policy->cpu))) {
-		up(&cpufreq_driver_sem);
+	if (!policy || !cpufreq_cpu_get(policy->cpu))
 		return -EINVAL;
-	}
 
+	down(&cpufreq_driver_sem);
 	memcpy(&policy->cpuinfo, 
 	       &cpufreq_driver->policy[policy->cpu].cpuinfo, 
 	       sizeof(struct cpufreq_cpuinfo));
+	up(&cpufreq_driver_sem);
 
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(policy);
-	if (ret) {
-		up(&cpufreq_driver_sem);
-		return ret;
-	}
+	if (ret)
+		goto error_out;
 
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 
 	/* adjust if necessary - all reasons */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST,
@@ -680,17 +713,18 @@
 	   which might be different to the first one */
 	ret = cpufreq_driver->verify(policy);
 	if (ret) {
-		up(&cpufreq_notifier_sem);
-		up(&cpufreq_driver_sem);
-		return ret;
+		up_read(&cpufreq_notifier_rwsem);
+		goto error_out;
 	}
 
 	/* notification of the new policy */
 	notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY,
 			    policy);
 
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 
+	/* from here on we limit it to one limit and/or governor change running at the moment */
+	down(&cpufreq_driver_sem);
 	cpufreq_driver->policy[policy->cpu].min    = policy->min;
 	cpufreq_driver->policy[policy->cpu].max    = policy->max;
 
@@ -718,9 +752,11 @@
 			cpufreq_governor(policy->cpu, CPUFREQ_GOV_LIMITS);
 		}
 	}
-	
 	up(&cpufreq_driver_sem);
 
+ error_out:	
+	cpufreq_cpu_put(policy->cpu);
+
 	return ret;
 }
 EXPORT_SYMBOL(cpufreq_set_policy);
@@ -766,7 +802,7 @@
  */
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
 {
-	down(&cpufreq_notifier_sem);
+	down_read(&cpufreq_notifier_rwsem);
 	switch (state) {
 	case CPUFREQ_PRECHANGE:
 		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
@@ -778,7 +814,7 @@
 		cpufreq_driver->policy[freqs->cpu].cur = freqs->new;
 		break;
 	}
-	up(&cpufreq_notifier_sem);
+	up_read(&cpufreq_notifier_rwsem);
 }
 EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
 
@@ -800,38 +836,33 @@
  */
 int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
-	int ret = 0;
-
-	if (cpufreq_driver)
-		return -EBUSY;
-	
-	if (!driver_data || !driver_data->verify || 
+	if (!driver_data || !driver_data->verify || !driver_data->init ||
 	    ((!driver_data->setpolicy) && (!driver_data->target)))
 		return -EINVAL;
 
-	down(&cpufreq_driver_sem);
 
+	if (kset_get(&cpufreq_interface.kset)) {
+		kset_put(&cpufreq_interface.kset);
+		return -EBUSY;
+	}
+
+	down(&cpufreq_driver_sem);
+	if (cpufreq_driver) {
+		up(&cpufreq_driver_sem);		
+		return -EBUSY;
+	}
 	cpufreq_driver = driver_data;
+	up(&cpufreq_driver_sem);
 
+	cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
 	if (!cpufreq_driver->policy) {
-		/* then we need per-CPU init */
-		if (!cpufreq_driver->init) {
-			up(&cpufreq_driver_sem);
-			return -EINVAL;
-		}
-		cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-		if (!cpufreq_driver->policy) {
-			up(&cpufreq_driver_sem);
-			return -ENOMEM;
-		}
-		memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
+		cpufreq_driver = NULL;
+		return -ENOMEM;
 	}
-	
-	up(&cpufreq_driver_sem);
 
-	ret = interface_register(&cpufreq_interface);
+	memset(cpufreq_driver->policy, 0, NR_CPUS * sizeof(struct cpufreq_policy));
 
-	return ret;
+	return interface_register(&cpufreq_interface);
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
@@ -846,20 +877,20 @@
  */
 int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
-	down(&cpufreq_driver_sem);
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
 
-	if (!cpufreq_driver || 
-	    ((driver != cpufreq_driver) && (driver != NULL))) { /* compat */
-		up(&cpufreq_driver_sem);
+	if (!cpufreq_driver || (driver != cpufreq_driver)) {
+		kset_put(&cpufreq_interface.kset);
 		return -EINVAL;
 	}
 
+	kset_put(&cpufreq_interface.kset);
 	interface_unregister(&cpufreq_interface);
 
-	if (driver)
-		kfree(cpufreq_driver->policy);
+	down(&cpufreq_driver_sem);
+	kfree(cpufreq_driver->policy);
 	cpufreq_driver = NULL;
-
 	up(&cpufreq_driver_sem);
 
 	return 0;
@@ -883,22 +914,28 @@
 	if (in_interrupt())
 		panic("cpufreq_restore() called from interrupt context!");
 
+	if (!kset_get(&cpufreq_interface.kset))
+		return 0;
+
+	if (!try_module_get(cpufreq_driver->owner))
+		goto error_out;
+
 	for (i=0;i<NR_CPUS;i++) {
-		if (!cpu_online(i))
+		if (!cpu_online(i) || !cpufreq_cpu_get(i))
 			continue;
 
 		down(&cpufreq_driver_sem);
-		if (!cpufreq_driver) {
-			up(&cpufreq_driver_sem);
-			return 0;
-		}
-
 		memcpy(&policy, &cpufreq_driver->policy[i], sizeof(struct cpufreq_policy));
 		up(&cpufreq_driver_sem);
-
 		ret += cpufreq_set_policy(&policy);
+
+		cpufreq_cpu_put(i);
 	}
 
+	module_put(cpufreq_driver->owner);
+ error_out:
+	kset_put(&cpufreq_interface.kset);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_restore);
diff -urN linux-2.5.64-bk4/kernel/posix-timers.c linux-2.5.64-bk5/kernel/posix-timers.c
--- linux-2.5.64-bk4/kernel/posix-timers.c	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk5/kernel/posix-timers.c	Mon Mar 31 12:27:44 2003
@@ -1273,7 +1273,7 @@
 		spin_unlock_irq(&nanosleep_abs_list_lock);
 	}
 	if (active) {
-		unsigned long jiffies_f = jiffies;
+		long jiffies_left;
 
 		/*
 		 * Always restart abs calls from scratch to pick up any
@@ -1282,7 +1282,12 @@
 		if (abs)
 			return -ERESTARTNOHAND;
 
-		jiffies_to_timespec(new_timer.expires - jiffies_f, tsave);
+		jiffies_left = new_timer.expires - jiffies;
+
+		if (jiffies_left < 0)
+			return 0;
+
+		jiffies_to_timespec(jiffies_left, tsave);
 
 		while (tsave->tv_nsec < 0) {
 			tsave->tv_nsec += NSEC_PER_SEC;
