aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCliff Wickman <cpw@sgi.com>2012-06-22 09:13:30 -0400
committerIngo Molnar <mingo@kernel.org>2012-06-25 08:45:04 -0400
commit26ef85770c765bb8b6b6922f8a413872dd8e3979 (patch)
tree3f09673f746331fd2e237661ccbf12b220d880f9 /arch
parent11cab711f686893f2696a061dfca30454a624784 (diff)
x86/uv: Implement UV BAU runtime enable and disable control via /proc/sgi_uv/
This patch enables the BAU to be turned on or off dynamically. echo "on" > /proc/sgi_uv/ptc_statistics echo "off" > /proc/sgi_uv/ptc_statistics The system may be booted with or without the nobau option. Whether the system currently has the BAU off can be seen in the /proc file -- normally with the baustats script. Each cpu will have a 1 in the bauoff field if the BAU was turned off, so baustats will give a count of cpus that have it off. Signed-off-by: Cliff Wickman <cpw@sgi.com> Link: http://lkml.kernel.org/r/20120622131330.GB31884@sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h2
-rw-r--r--arch/x86/platform/uv/tlb_uv.c76
2 files changed, 63 insertions, 15 deletions
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index 6149b476d9df..847c00b721b2 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -520,6 +520,7 @@ struct ptc_stats {
520 unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */ 520 unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */
521 unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */ 521 unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */
522 unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */ 522 unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */
523 unsigned long s_enters; /* entries to the driver */
523 /* destination statistics */ 524 /* destination statistics */
524 unsigned long d_alltlb; /* times all tlb's on this 525 unsigned long d_alltlb; /* times all tlb's on this
525 cpu were flushed */ 526 cpu were flushed */
@@ -586,6 +587,7 @@ struct bau_control {
586 int timeout_tries; 587 int timeout_tries;
587 int ipi_attempts; 588 int ipi_attempts;
588 int conseccompletes; 589 int conseccompletes;
590 short nobau;
589 int baudisabled; 591 int baudisabled;
590 int set_bau_off; 592 int set_bau_off;
591 short cpu; 593 short cpu;
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 0c48d438cbba..1492170cbb5a 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -38,6 +38,7 @@ static int timeout_base_ns[] = {
38 38
39static int timeout_us; 39static int timeout_us;
40static int nobau; 40static int nobau;
41static int nobau_perm;
41static int baudisabled; 42static int baudisabled;
42static spinlock_t disable_lock; 43static spinlock_t disable_lock;
43static cycles_t congested_cycles; 44static cycles_t congested_cycles;
@@ -120,6 +121,40 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
120static DEFINE_PER_CPU(struct bau_control, bau_control); 121static DEFINE_PER_CPU(struct bau_control, bau_control);
121static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); 122static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
122 123
124static void
125set_bau_on(void)
126{
127 int cpu;
128 struct bau_control *bcp;
129
130 if (nobau_perm) {
131 pr_info("BAU not initialized; cannot be turned on\n");
132 return;
133 }
134 nobau = 0;
135 for_each_present_cpu(cpu) {
136 bcp = &per_cpu(bau_control, cpu);
137 bcp->nobau = 0;
138 }
139 pr_info("BAU turned on\n");
140 return;
141}
142
143static void
144set_bau_off(void)
145{
146 int cpu;
147 struct bau_control *bcp;
148
149 nobau = 1;
150 for_each_present_cpu(cpu) {
151 bcp = &per_cpu(bau_control, cpu);
152 bcp->nobau = 1;
153 }
154 pr_info("BAU turned off\n");
155 return;
156}
157
123/* 158/*
124 * Determine the first node on a uvhub. 'Nodes' are used for kernel 159 * Determine the first node on a uvhub. 'Nodes' are used for kernel
125 * memory allocation. 160 * memory allocation.
@@ -1079,12 +1114,12 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
1079 struct ptc_stats *stat; 1114 struct ptc_stats *stat;
1080 struct bau_control *bcp; 1115 struct bau_control *bcp;
1081 1116
1082 /* kernel was booted 'nobau' */
1083 if (nobau)
1084 return cpumask;
1085
1086 bcp = &per_cpu(bau_control, cpu); 1117 bcp = &per_cpu(bau_control, cpu);
1087 stat = bcp->statp; 1118 stat = bcp->statp;
1119 stat->s_enters++;
1120
1121 if (bcp->nobau)
1122 return cpumask;
1088 1123
1089 /* bau was disabled due to slow response */ 1124 /* bau was disabled due to slow response */
1090 if (bcp->baudisabled) { 1125 if (bcp->baudisabled) {
@@ -1338,29 +1373,32 @@ static inline unsigned long long usec_2_cycles(unsigned long microsec)
1338static int ptc_seq_show(struct seq_file *file, void *data) 1373static int ptc_seq_show(struct seq_file *file, void *data)
1339{ 1374{
1340 struct ptc_stats *stat; 1375 struct ptc_stats *stat;
1376 struct bau_control *bcp;
1341 int cpu; 1377 int cpu;
1342 1378
1343 cpu = *(loff_t *)data; 1379 cpu = *(loff_t *)data;
1344 if (!cpu) { 1380 if (!cpu) {
1345 seq_printf(file, 1381 seq_printf(file,
1346 "# cpu sent stime self locals remotes ncpus localhub "); 1382 "# cpu bauoff sent stime self locals remotes ncpus localhub ");
1347 seq_printf(file, 1383 seq_printf(file,
1348 "remotehub numuvhubs numuvhubs16 numuvhubs8 "); 1384 "remotehub numuvhubs numuvhubs16 numuvhubs8 ");
1349 seq_printf(file, 1385 seq_printf(file,
1350 "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok "); 1386 "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok ");
1351 seq_printf(file, 1387 seq_printf(file,
1352 "resetp resett giveup sto bz throt swack recv rtime "); 1388 "resetp resett giveup sto bz throt enters swack recv rtime ");
1353 seq_printf(file, 1389 seq_printf(file,
1354 "all one mult none retry canc nocan reset rcan "); 1390 "all one mult none retry canc nocan reset rcan ");
1355 seq_printf(file, 1391 seq_printf(file,
1356 "disable enable wars warshw warwaits\n"); 1392 "disable enable wars warshw warwaits\n");
1357 } 1393 }
1358 if (cpu < num_possible_cpus() && cpu_online(cpu)) { 1394 if (cpu < num_possible_cpus() && cpu_online(cpu)) {
1359 stat = &per_cpu(ptcstats, cpu); 1395 bcp = &per_cpu(bau_control, cpu);
1396 stat = bcp->statp;
1360 /* source side statistics */ 1397 /* source side statistics */
1361 seq_printf(file, 1398 seq_printf(file,
1362 "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", 1399 "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
1363 cpu, stat->s_requestor, cycles_2_us(stat->s_time), 1400 cpu, bcp->nobau, stat->s_requestor,
1401 cycles_2_us(stat->s_time),
1364 stat->s_ntargself, stat->s_ntarglocals, 1402 stat->s_ntargself, stat->s_ntarglocals,
1365 stat->s_ntargremotes, stat->s_ntargcpu, 1403 stat->s_ntargremotes, stat->s_ntargcpu,
1366 stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub, 1404 stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub,
@@ -1369,11 +1407,11 @@ static int ptc_seq_show(struct seq_file *file, void *data)
1369 stat->s_ntarguvhub8, stat->s_ntarguvhub4, 1407 stat->s_ntarguvhub8, stat->s_ntarguvhub4,
1370 stat->s_ntarguvhub2, stat->s_ntarguvhub1, 1408 stat->s_ntarguvhub2, stat->s_ntarguvhub1,
1371 stat->s_dtimeout, stat->s_strongnacks); 1409 stat->s_dtimeout, stat->s_strongnacks);
1372 seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ", 1410 seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld ",
1373 stat->s_retry_messages, stat->s_retriesok, 1411 stat->s_retry_messages, stat->s_retriesok,
1374 stat->s_resets_plug, stat->s_resets_timeout, 1412 stat->s_resets_plug, stat->s_resets_timeout,
1375 stat->s_giveup, stat->s_stimeout, 1413 stat->s_giveup, stat->s_stimeout,
1376 stat->s_busy, stat->s_throttles); 1414 stat->s_busy, stat->s_throttles, stat->s_enters);
1377 1415
1378 /* destination side statistics */ 1416 /* destination side statistics */
1379 seq_printf(file, 1417 seq_printf(file,
@@ -1438,6 +1476,14 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,
1438 return -EFAULT; 1476 return -EFAULT;
1439 optstr[count - 1] = '\0'; 1477 optstr[count - 1] = '\0';
1440 1478
1479 if (!strcmp(optstr, "on")) {
1480 set_bau_on();
1481 return count;
1482 } else if (!strcmp(optstr, "off")) {
1483 set_bau_off();
1484 return count;
1485 }
1486
1441 if (strict_strtol(optstr, 10, &input_arg) < 0) { 1487 if (strict_strtol(optstr, 10, &input_arg) < 0) {
1442 printk(KERN_DEBUG "%s is invalid\n", optstr); 1488 printk(KERN_DEBUG "%s is invalid\n", optstr);
1443 return -EINVAL; 1489 return -EINVAL;
@@ -1836,6 +1882,8 @@ static void __init init_per_cpu_tunables(void)
1836 for_each_present_cpu(cpu) { 1882 for_each_present_cpu(cpu) {
1837 bcp = &per_cpu(bau_control, cpu); 1883 bcp = &per_cpu(bau_control, cpu);
1838 bcp->baudisabled = 0; 1884 bcp->baudisabled = 0;
1885 if (nobau)
1886 bcp->nobau = 1;
1839 bcp->statp = &per_cpu(ptcstats, cpu); 1887 bcp->statp = &per_cpu(ptcstats, cpu);
1840 /* time interval to catch a hardware stay-busy bug */ 1888 /* time interval to catch a hardware stay-busy bug */
1841 bcp->timeout_interval = usec_2_cycles(2*timeout_us); 1889 bcp->timeout_interval = usec_2_cycles(2*timeout_us);
@@ -2069,9 +2117,6 @@ static int __init uv_bau_init(void)
2069 if (!is_uv_system()) 2117 if (!is_uv_system())
2070 return 0; 2118 return 0;
2071 2119
2072 if (nobau)
2073 return 0;
2074
2075 for_each_possible_cpu(cur_cpu) { 2120 for_each_possible_cpu(cur_cpu) {
2076 mask = &per_cpu(uv_flush_tlb_mask, cur_cpu); 2121 mask = &per_cpu(uv_flush_tlb_mask, cur_cpu);
2077 zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu)); 2122 zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
@@ -2091,7 +2136,8 @@ static int __init uv_bau_init(void)
2091 enable_timeouts(); 2136 enable_timeouts();
2092 2137
2093 if (init_per_cpu(nuvhubs, uv_base_pnode)) { 2138 if (init_per_cpu(nuvhubs, uv_base_pnode)) {
2094 nobau = 1; 2139 set_bau_off();
2140 nobau_perm = 1;
2095 return 0; 2141 return 0;
2096 } 2142 }
2097 2143