Commit 6a81f32d authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/sparc-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents fccd3231 7662c9d2
...@@ -43,6 +43,9 @@ CONFIG_HW_CONSOLE=y ...@@ -43,6 +43,9 @@ CONFIG_HW_CONSOLE=y
CONFIG_SMP=y CONFIG_SMP=y
# CONFIG_PREEMPT is not set # CONFIG_PREEMPT is not set
CONFIG_NR_CPUS=4 CONFIG_NR_CPUS=4
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_PROC_INTF=y
CONFIG_US3_FREQ=m
CONFIG_SPARC64=y CONFIG_SPARC64=y
CONFIG_HOTPLUG=y CONFIG_HOTPLUG=y
CONFIG_HAVE_DEC_LOCK=y CONFIG_HAVE_DEC_LOCK=y
...@@ -188,13 +191,13 @@ CONFIG_BLK_DEV_ALI15X3=y ...@@ -188,13 +191,13 @@ CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_WDC_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set # CONFIG_BLK_DEV_AMD74XX is not set
CONFIG_BLK_DEV_CMD64X=y CONFIG_BLK_DEV_CMD64X=y
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set # CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_NFORCE is not set
CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_NS87415=y
# CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set
...@@ -644,6 +647,8 @@ CONFIG_NFSD_V3=y ...@@ -644,6 +647,8 @@ CONFIG_NFSD_V3=y
CONFIG_NFSD_V4=y CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y CONFIG_NFSD_TCP=y
CONFIG_SUNRPC=m CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_LOCKD=m CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m CONFIG_EXPORTFS=m
...@@ -878,7 +883,7 @@ CONFIG_USB_SERIAL_WHITEHEAT=m ...@@ -878,7 +883,7 @@ CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
CONFIG_USB_SERIAL_EMPEG=m CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_VISOR=m # CONFIG_USB_SERIAL_VISOR is not set
CONFIG_USB_SERIAL_IPAQ=m CONFIG_USB_SERIAL_IPAQ=m
# CONFIG_USB_SERIAL_IR is not set # CONFIG_USB_SERIAL_IR is not set
CONFIG_USB_SERIAL_EDGEPORT=m CONFIG_USB_SERIAL_EDGEPORT=m
...@@ -975,6 +980,7 @@ CONFIG_CRYPTO_MD4=y ...@@ -975,6 +980,7 @@ CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_TWOFISH=m
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/console.h> #include <linux/console.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/cpu.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -677,3 +678,21 @@ void sun_do_break(void) ...@@ -677,3 +678,21 @@ void sun_do_break(void)
int serial_console; int serial_console;
int stop_a_enabled = 1; int stop_a_enabled = 1;
static struct cpu *sparc64_cpus;
static int __init topology_init(void)
{
int i;
sparc64_cpus = kmalloc(NR_CPUS * sizeof(struct cpu), GFP_KERNEL);
if (!sparc64_cpus)
return -ENOMEM;
for (i = 0; i < NR_CPUS; i++) {
if (cpu_possible(i))
register_cpu(&sparc64_cpus[i], i, NULL);
}
return 0;
}
subsys_initcall(topology_init);
...@@ -2298,10 +2298,27 @@ static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_up ...@@ -2298,10 +2298,27 @@ static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_up
__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
clen64 = kcmsg32->cmsg_len; clen64 = kcmsg32->cmsg_len;
if (kcmsg32->cmsg_level == SOL_SOCKET &&
kcmsg32->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
struct compat_timeval *tv32;
if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
kfree(workbuf);
goto fail;
}
copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32);
tv32->tv_sec = tv.tv_sec;
tv32->tv_usec = tv.tv_usec;
clen32 = sizeof(*tv32) +
CMSG32_ALIGN(sizeof(struct cmsghdr32));
} else {
copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
clen64 - CMSG_ALIGN(sizeof(*ucmsg))); clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
CMSG32_ALIGN(sizeof(struct cmsghdr32))); CMSG32_ALIGN(sizeof(struct cmsghdr32)));
}
kcmsg32->cmsg_len = clen32; kcmsg32->cmsg_len = clen32;
ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
......
...@@ -15,12 +15,19 @@ ...@@ -15,12 +15,19 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/head.h>
static struct cpufreq_driver *cpufreq_us3_driver; static struct cpufreq_driver *cpufreq_us3_driver;
/* Index by [(CPU * 4) + INDEX] (first three indices are struct us3_freq_percpu_info {
* actual us3 divisor entries, last is for CPUFREQ_TABLE_END) struct cpufreq_frequency_table table[4];
*/ unsigned long udelay_val_ref;
static struct cpufreq_frequency_table *us3_freq_table; unsigned long clock_tick_ref;
unsigned int ref_freq;
};
/* Indexed by cpu number. */
static struct us3_freq_percpu_info *us3_freq_table;
/* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled /* UltraSPARC-III has three dividers: 1, 2, and 32. These are controlled
* in the Safari config register. * in the Safari config register.
...@@ -51,17 +58,66 @@ static void write_safari_cfg(unsigned long val) ...@@ -51,17 +58,66 @@ static void write_safari_cfg(unsigned long val)
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
extern unsigned long up_clock_tick; extern unsigned long up_clock_tick;
unsigned long clock_tick_ref;
unsigned int ref_freq;
#endif #endif
static __inline__ unsigned long get_clock_tick(unsigned int cpu) static __inline__ unsigned long get_clock_tick(unsigned int cpu)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
if (us3_freq_table[cpu].clock_tick_ref)
return us3_freq_table[cpu].clock_tick_ref;
return cpu_data[cpu].clock_tick; return cpu_data[cpu].clock_tick;
#else #else
if (clock_tick_ref)
return clock_tick_ref;
return up_clock_tick; return up_clock_tick;
#endif #endif
} }
static int us3_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
unsigned int cpu = freq->cpu;
#ifdef CONFIG_SMP
if (!us3_freq_table[cpu].ref_freq) {
us3_freq_table[cpu].ref_freq = freq->old;
us3_freq_table[cpu].udelay_val_ref = cpu_data[cpu].udelay_val;
us3_freq_table[cpu].clock_tick_ref = cpu_data[cpu].clock_tick;
}
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
cpu_data[cpu].udelay_val =
cpufreq_scale(us3_freq_table[cpu].udelay_val_ref,
us3_freq_table[cpu].ref_freq,
freq->new);
cpu_data[cpu].clock_tick =
cpufreq_scale(us3_freq_table[cpu].clock_tick_ref,
us3_freq_table[cpu].ref_freq,
freq->new);
}
#else
/* In the non-SMP case, kernel/cpufreq.c takes care of adjusting
* loops_per_jiffy.
*/
if (!ref_freq) {
ref_freq = freq->old;
clock_tick_ref = up_clock_tick;
}
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new))
up_clock_tick = cpufreq_scale(clock_tick_ref, ref_freq, freq->new);
#endif
return 0;
}
static struct notifier_block us3_cpufreq_notifier_block = {
.notifier_call = us3_cpufreq_notifier
};
static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg) static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg)
{ {
unsigned long clock_tick = get_clock_tick(cpu); unsigned long clock_tick = get_clock_tick(cpu);
...@@ -130,12 +186,12 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index) ...@@ -130,12 +186,12 @@ static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
set_cpus_allowed(current, cpus_allowed); set_cpus_allowed(current, cpus_allowed);
} }
static int us3_setpolicy(struct cpufreq_policy *policy) static int us3freq_setpolicy(struct cpufreq_policy *policy)
{ {
unsigned int new_index = 0; unsigned int new_index = 0;
if (cpufreq_frequency_table_setpolicy(policy, if (cpufreq_frequency_table_setpolicy(policy,
&us3_freq_table[(policy->cpu * 4) + 0], &us3_freq_table[policy->cpu].table[0],
&new_index)) &new_index))
return -EINVAL; return -EINVAL;
...@@ -144,83 +200,98 @@ static int us3_setpolicy(struct cpufreq_policy *policy) ...@@ -144,83 +200,98 @@ static int us3_setpolicy(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int us3_verify(struct cpufreq_policy *policy) static int us3freq_verify(struct cpufreq_policy *policy)
{ {
return cpufreq_frequency_table_verify(policy, return cpufreq_frequency_table_verify(policy,
&us3_freq_table[(policy->cpu * 4) + 0]); &us3_freq_table[policy->cpu].table[0]);
} }
#ifndef CONFIG_SMP static int __init us3freq_cpu_init(struct cpufreq_policy *policy)
extern unsigned long up_clock_tick;
#endif
static void __init us3_init_freq_table(unsigned int cpu)
{ {
unsigned int cpu = policy->cpu;
unsigned long clock_tick = get_clock_tick(cpu); unsigned long clock_tick = get_clock_tick(cpu);
struct cpufreq_frequency_table *table =
&us3_freq_table[cpu].table[0];
table[0].index = 0;
table[0].frequency = clock_tick / 1;
table[1].index = 1;
table[1].frequency = clock_tick / 2;
table[2].index = 2;
table[2].frequency = clock_tick / 32;
table[3].index = 0;
table[3].frequency = CPUFREQ_TABLE_END;
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->cpuinfo.transition_latency = 0;
return cpufreq_frequency_table_cpuinfo(policy, table);
}
static int __exit us3freq_cpu_exit(struct cpufreq_policy *policy)
{
if (cpufreq_us3_driver)
us3_set_cpu_divider_index(policy->cpu, 0);
us3_freq_table[(cpu * 4) + 0].index = 0; return 0;
us3_freq_table[(cpu * 4) + 0].frequency = clock_tick / 1;
us3_freq_table[(cpu * 4) + 1].index = 1;
us3_freq_table[(cpu * 4) + 1].frequency = clock_tick / 2;
us3_freq_table[(cpu * 4) + 2].index = 2;
us3_freq_table[(cpu * 4) + 2].frequency = clock_tick / 32;
us3_freq_table[(cpu * 4) + 3].index = 0;
us3_freq_table[(cpu * 4) + 3].frequency = CPUFREQ_TABLE_END;
} }
static int __init us3freq_init(void) static int __init us3freq_init(void)
{ {
struct cpufreq_driver *driver;
unsigned long manuf, impl, ver; unsigned long manuf, impl, ver;
int i, ret; int ret;
__asm__("rdpr %%ver, %0" : "=r" (ver)); __asm__("rdpr %%ver, %0" : "=r" (ver));
manuf = ((ver >> 48) & 0xffff); manuf = ((ver >> 48) & 0xffff);
impl = ((ver >> 32) & 0xffff); impl = ((ver >> 32) & 0xffff);
/* XXX Maybe accept cheetah+ too? */ if (manuf == CHEETAH_MANUF &&
if (manuf == 0x3e && impl == 0x14) { (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL)) {
driver = kmalloc(sizeof(struct cpufreq_driver) + struct cpufreq_driver *driver;
(NR_CPUS * sizeof(struct cpufreq_policy)),
GFP_KERNEL); cpufreq_register_notifier(&us3_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
ret = -ENOMEM;
driver = kmalloc(sizeof(struct cpufreq_driver), GFP_KERNEL);
if (!driver) if (!driver)
return -ENOMEM; goto err_out;
memset(driver, 0, sizeof(*driver));
us3_freq_table = kmalloc( us3_freq_table = kmalloc(
(NR_CPUS * 4 * sizeof(struct cpufreq_frequency_table)), (NR_CPUS * sizeof(struct us3_freq_percpu_info)),
GFP_KERNEL); GFP_KERNEL);
if (!us3_freq_table) { if (!us3_freq_table)
kfree(driver); goto err_out;
return -ENOMEM;
}
driver->policy = (struct cpufreq_policy *) (driver + 1); memset(us3_freq_table, 0,
driver->verify = us3_verify; (NR_CPUS * sizeof(struct us3_freq_percpu_info)));
driver->setpolicy = us3_setpolicy;
driver->verify = us3freq_verify;
driver->setpolicy = us3freq_setpolicy;
driver->init = us3freq_cpu_init;
driver->exit = us3freq_cpu_exit;
strcpy(driver->name, "UltraSPARC-III");
for (i = 0; i < NR_CPUS; i++) {
driver->policy[i].cpu = i;
us3_init_freq_table(i);
ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i],
&us3_freq_table[(i * 4) + 0]);
if (ret) {
kfree(driver);
kfree(us3_freq_table);
us3_freq_table = NULL;
return ret;
}
driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
us3_set_cpu_divider_index(i, 0);
}
cpufreq_us3_driver = driver; cpufreq_us3_driver = driver;
ret = cpufreq_register_driver(driver); ret = cpufreq_register_driver(driver);
if (ret) { if (ret)
goto err_out;
return 0;
err_out:
if (driver) {
kfree(driver); kfree(driver);
cpufreq_us3_driver = NULL; cpufreq_us3_driver = NULL;
}
if (us3_freq_table) {
kfree(us3_freq_table); kfree(us3_freq_table);
us3_freq_table = NULL; us3_freq_table = NULL;
return ret;
} }
return 0; cpufreq_unregister_notifier(&us3_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
return ret;
} }
return -ENODEV; return -ENODEV;
...@@ -228,12 +299,10 @@ static int __init us3freq_init(void) ...@@ -228,12 +299,10 @@ static int __init us3freq_init(void)
static void __exit us3freq_exit(void) static void __exit us3freq_exit(void)
{ {
int i;
if (cpufreq_us3_driver) { if (cpufreq_us3_driver) {
for (i = 0; i < NR_CPUS; i++)
us3_set_cpu_divider_index(i, 0);
cpufreq_unregister_driver(cpufreq_us3_driver); cpufreq_unregister_driver(cpufreq_us3_driver);
cpufreq_unregister_notifier(&us3_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
kfree(cpufreq_us3_driver); kfree(cpufreq_us3_driver);
cpufreq_us3_driver = NULL; cpufreq_us3_driver = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment