summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/idle.c7
-rw-r--r--arch/ppc64/kernel/prom.c46
-rw-r--r--arch/ppc64/kernel/sysfs.c89
-rw-r--r--include/asm-ppc64/naca.h6
4 files changed, 95 insertions, 53 deletions
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index b30aea273974..a9a501df397c 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -161,13 +161,14 @@ int default_idle(void)
#ifdef CONFIG_PPC_PSERIES
-DECLARE_PER_CPU(smt_snooze_delay);
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
int dedicated_idle(void)
{
long oldval;
struct paca_struct *lpaca = get_paca(), *ppaca;
unsigned long start_snooze;
+ unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
ppaca = &paca[smp_processor_id() ^ 1];
@@ -180,14 +181,14 @@ int dedicated_idle(void)
if (!oldval) {
set_thread_flag(TIF_POLLING_NRFLAG);
start_snooze = __get_tb() +
- naca->smt_snooze_delay*tb_ticks_per_usec;
+ *smt_snooze_delay * tb_ticks_per_usec;
while (!need_resched()) {
/* need_resched could be 1 or 0 at this
* point. If it is 0, set it to 0, so
* an IPI/Prod is sent. If it is 1, keep
* it that way & schedule work.
*/
- if (naca->smt_snooze_delay == 0 ||
+ if (*smt_snooze_delay == 0 ||
__get_tb() < start_snooze) {
HMT_low(); /* Low thread priority */
continue;
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index f1cfd43dd39c..6748b2244e88 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -1254,7 +1254,6 @@ smt_setup(void)
{
char *p, *q;
char my_smt_enabled = SMT_DYNAMIC;
- unsigned long my_smt_snooze_delay;
ihandle prom_options = NULL;
char option[9];
unsigned long offset = reloc_offset();
@@ -1301,51 +1300,6 @@ smt_setup(void)
if (!found )
my_smt_enabled = SMT_DYNAMIC; /* default to on */
- found = 0;
- if (my_smt_enabled) {
- if (strstr(RELOC(cmd_line), RELOC("smt-snooze-delay="))) {
- for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-snooze-delay="))) != 0; ) {
- q = p + 17;
- if (p > RELOC(cmd_line) && p[-1] != ' ')
- continue;
- found = 1;
- /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
- my_smt_snooze_delay = 0;
- while (*q >= '0' && *q <= '9') {
- my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
- q++;
- }
- }
- }
-
- if (!found) {
- prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
- if (prom_options != (ihandle) -1) {
- call_prom(RELOC("getprop"),
- 4, 1, prom_options,
- RELOC("ibm,smt-snooze-delay"),
- option,
- sizeof(option));
- if (option[0] != 0) {
- found = 1;
- /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
- my_smt_snooze_delay = 0;
- q = option;
- while (*q >= '0' && *q <= '9') {
- my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
- q++;
- }
- }
- }
- }
-
- if (!found) {
- my_smt_snooze_delay = 0; /* default value */
- }
- } else {
- my_smt_snooze_delay = 0; /* default value */
- }
- _naca->smt_snooze_delay = my_smt_snooze_delay;
_naca->smt_state = my_smt_enabled;
}
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 05ef5291a737..3bcbdec74195 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -9,6 +9,90 @@
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/hvcall.h>
+#include <asm/prom.h>
+
+
+/* SMT stuff */
+
+#ifndef CONFIG_PPC_ISERIES
+
+/* default to snooze disabled */
+DEFINE_PER_CPU(unsigned long, smt_snooze_delay);
+
+static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+ ssize_t ret;
+ unsigned long snooze;
+
+ ret = sscanf(buf, "%lu", &snooze);
+ if (ret != 1)
+ return -EINVAL;
+
+ per_cpu(smt_snooze_delay, cpu->sysdev.id) = snooze;
+
+ return count;
+}
+
+static ssize_t show_smt_snooze_delay(struct sys_device *dev, char *buf)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+
+ return sprintf(buf, "%lu\n", per_cpu(smt_snooze_delay, cpu->sysdev.id));
+}
+
+static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
+ store_smt_snooze_delay);
+
+/* Only parse OF options if the matching cmdline option was not specified */
+static int smt_snooze_cmdline;
+
+static int __init smt_setup(void)
+{
+ struct device_node *options;
+ unsigned int *val;
+ unsigned int cpu;
+
+ if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ return 1;
+
+ options = find_path_device("/options");
+ if (!options)
+ return 1;
+
+ val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
+ NULL);
+ if (!smt_snooze_cmdline && val) {
+ for_each_cpu(cpu)
+ per_cpu(smt_snooze_delay, cpu) = *val;
+ }
+
+ return 1;
+}
+__initcall(smt_setup);
+
+static int __init setup_smt_snooze_delay(char *str)
+{
+ unsigned int cpu;
+ int snooze;
+
+ if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ return 1;
+
+ smt_snooze_cmdline = 1;
+
+ if (get_option(&str, &snooze)) {
+ for_each_cpu(cpu)
+ per_cpu(smt_snooze_delay, cpu) = snooze;
+ }
+
+ return 1;
+}
+__setup("smt-snooze-delay=", setup_smt_snooze_delay);
+
+#endif
+
/* PMC stuff */
@@ -235,6 +319,11 @@ static int __init topology_init(void)
register_cpu_pmc(&c->sysdev);
sysdev_create_file(&c->sysdev, &attr_physical_id);
+
+#ifndef CONFIG_PPC_ISERIES
+ if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ sysdev_create_file(&c->sysdev, &attr_smt_snooze_delay);
+#endif
}
return 0;
diff --git a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h
index b93cdf160dd3..a50189402420 100644
--- a/include/asm-ppc64/naca.h
+++ b/include/asm-ppc64/naca.h
@@ -37,12 +37,10 @@ struct naca_struct {
u32 dCacheL1LinesPerPage; /* L1 d-cache lines / page 0x64 */
u32 iCacheL1LogLineSize; /* L1 i-cache line size Log2 0x68 */
u32 iCacheL1LinesPerPage; /* L1 i-cache lines / page 0x6c */
- u64 smt_snooze_delay; /* Delay (in usec) before 0x70 */
- /* entering ST mode */
- u8 smt_state; /* 0 = SMT off 0x78 */
+ u8 smt_state; /* 0 = SMT off 0x70 */
/* 1 = SMT on */
/* 2 = SMT dynamic */
- u8 resv0[7]; /* Reserved 0x70 - 0x7F */
+ u8 resv0[15]; /* Reserved 0x71 - 0x7F */
};
extern struct naca_struct *naca;