## 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 - /* 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 "); 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 #include #include +#include #include @@ -112,7 +113,7 @@ if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target_l(¤t_policy[cpu], freq, + ret = cpufreq_driver_target(¤t_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 (¤t_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 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 #include - -#ifdef PCMCIA -#undef MODULE -#endif - -#include /* for CONFIG_PCI */ #include #include #include @@ -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: No BIOS, using port_base = 0x%x, irq = %d\n", @@ -895,7 +884,7 @@ printk( "scsi: Cannot locate chip at port base 0x%x\n", port_base ); printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - return 0; + return NULL; } } else { int flag = 0; @@ -910,7 +899,7 @@ if (!flag) { printk( "scsi: Detection failed (no card)\n" ); - return 0; + return NULL; } } } @@ -936,7 +925,7 @@ if (setup_called) { printk(KERN_ERR "scsi: 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: 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: 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 . -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 #include + +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 - -#ifdef PCMCIA -#undef MODULE -#endif - #include /* to get disk capacity */ #include #include @@ -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 #endif #include +#include #include -#include #include #include #include @@ -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 #include #include - +#include +#include #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; ipolicy[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;ipolicy[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;