diff options
Diffstat (limited to 'arch/x86/kernel/tlb_uv.c')
| -rw-r--r-- | arch/x86/kernel/tlb_uv.c | 281 |
1 files changed, 241 insertions, 40 deletions
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 5506836c4a82..c8661779c51e 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | */ | 8 | */ |
| 9 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
| 10 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
| 11 | #include <linux/debugfs.h> | ||
| 11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 12 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 13 | 14 | ||
| @@ -42,12 +43,22 @@ static int timeout_base_ns[] = { | |||
| 42 | 167772160 | 43 | 167772160 |
| 43 | }; | 44 | }; |
| 44 | static int timeout_us; | 45 | static int timeout_us; |
| 46 | static int nobau; | ||
| 45 | 47 | ||
| 46 | #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL | 48 | /* tunables: */ |
| 47 | 49 | static int max_bau_concurrent = MAX_BAU_CONCURRENT; | |
| 48 | static int uv_bau_max_concurrent __read_mostly; | 50 | static int max_bau_concurrent_constant = MAX_BAU_CONCURRENT; |
| 51 | static int plugged_delay = PLUGGED_DELAY; | ||
| 52 | static int plugsb4reset = PLUGSB4RESET; | ||
| 53 | static int timeoutsb4reset = TIMEOUTSB4RESET; | ||
| 54 | static int ipi_reset_limit = IPI_RESET_LIMIT; | ||
| 55 | static int complete_threshold = COMPLETE_THRESHOLD; | ||
| 56 | static int congested_response_us = CONGESTED_RESPONSE_US; | ||
| 57 | static int congested_reps = CONGESTED_REPS; | ||
| 58 | static int congested_period = CONGESTED_PERIOD; | ||
| 59 | static struct dentry *tunables_dir; | ||
| 60 | static struct dentry *tunables_file; | ||
| 49 | 61 | ||
| 50 | static int nobau; | ||
| 51 | static int __init setup_nobau(char *arg) | 62 | static int __init setup_nobau(char *arg) |
| 52 | { | 63 | { |
| 53 | nobau = 1; | 64 | nobau = 1; |
| @@ -539,23 +550,24 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 539 | unsigned long index; | 550 | unsigned long index; |
| 540 | cycles_t time1; | 551 | cycles_t time1; |
| 541 | cycles_t time2; | 552 | cycles_t time2; |
| 553 | cycles_t elapsed; | ||
| 542 | struct ptc_stats *stat = &per_cpu(ptcstats, bcp->cpu); | 554 | struct ptc_stats *stat = &per_cpu(ptcstats, bcp->cpu); |
| 543 | struct bau_control *smaster = bcp->socket_master; | 555 | struct bau_control *smaster = bcp->socket_master; |
| 544 | struct bau_control *hmaster = bcp->uvhub_master; | 556 | struct bau_control *hmaster = bcp->uvhub_master; |
| 545 | 557 | ||
| 546 | /* | 558 | /* |
| 547 | * Spin here while there are hmaster->max_concurrent or more active | 559 | * Spin here while there are hmaster->max_bau_concurrent or more active |
| 548 | * descriptors. This is the per-uvhub 'throttle'. | 560 | * descriptors. This is the per-uvhub 'throttle'. |
| 549 | */ | 561 | */ |
| 550 | if (!atomic_inc_unless_ge(&hmaster->uvhub_lock, | 562 | if (!atomic_inc_unless_ge(&hmaster->uvhub_lock, |
| 551 | &hmaster->active_descriptor_count, | 563 | &hmaster->active_descriptor_count, |
| 552 | hmaster->max_concurrent)) { | 564 | hmaster->max_bau_concurrent)) { |
| 553 | stat->s_throttles++; | 565 | stat->s_throttles++; |
| 554 | do { | 566 | do { |
| 555 | cpu_relax(); | 567 | cpu_relax(); |
| 556 | } while (!atomic_inc_unless_ge(&hmaster->uvhub_lock, | 568 | } while (!atomic_inc_unless_ge(&hmaster->uvhub_lock, |
| 557 | &hmaster->active_descriptor_count, | 569 | &hmaster->active_descriptor_count, |
| 558 | hmaster->max_concurrent)); | 570 | hmaster->max_bau_concurrent)); |
| 559 | } | 571 | } |
| 560 | 572 | ||
| 561 | while (hmaster->uvhub_quiesce) | 573 | while (hmaster->uvhub_quiesce) |
| @@ -609,9 +621,9 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 609 | * that case hardware immediately returns the ERROR | 621 | * that case hardware immediately returns the ERROR |
| 610 | * that looks like a destination timeout. | 622 | * that looks like a destination timeout. |
| 611 | */ | 623 | */ |
| 612 | udelay(TIMEOUT_DELAY); | 624 | udelay(bcp->plugged_delay); |
| 613 | bcp->plugged_tries++; | 625 | bcp->plugged_tries++; |
| 614 | if (bcp->plugged_tries >= PLUGSB4RESET) { | 626 | if (bcp->plugged_tries >= bcp->plugsb4reset) { |
| 615 | bcp->plugged_tries = 0; | 627 | bcp->plugged_tries = 0; |
| 616 | quiesce_local_uvhub(hmaster); | 628 | quiesce_local_uvhub(hmaster); |
| 617 | spin_lock(&hmaster->queue_lock); | 629 | spin_lock(&hmaster->queue_lock); |
| @@ -623,10 +635,10 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 623 | stat->s_resets_plug++; | 635 | stat->s_resets_plug++; |
| 624 | } | 636 | } |
| 625 | } else if (completion_status == FLUSH_RETRY_TIMEOUT) { | 637 | } else if (completion_status == FLUSH_RETRY_TIMEOUT) { |
| 626 | hmaster->max_concurrent = 1; | 638 | hmaster->max_bau_concurrent = 1; |
| 627 | bcp->timeout_tries++; | 639 | bcp->timeout_tries++; |
| 628 | udelay(TIMEOUT_DELAY); | 640 | udelay(TIMEOUT_DELAY); |
| 629 | if (bcp->timeout_tries >= TIMEOUTSB4RESET) { | 641 | if (bcp->timeout_tries >= bcp->timeoutsb4reset) { |
| 630 | bcp->timeout_tries = 0; | 642 | bcp->timeout_tries = 0; |
| 631 | quiesce_local_uvhub(hmaster); | 643 | quiesce_local_uvhub(hmaster); |
| 632 | spin_lock(&hmaster->queue_lock); | 644 | spin_lock(&hmaster->queue_lock); |
| @@ -638,7 +650,7 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 638 | stat->s_resets_timeout++; | 650 | stat->s_resets_timeout++; |
| 639 | } | 651 | } |
| 640 | } | 652 | } |
| 641 | if (bcp->ipi_attempts >= 3) { | 653 | if (bcp->ipi_attempts >= bcp->ipi_reset_limit) { |
| 642 | bcp->ipi_attempts = 0; | 654 | bcp->ipi_attempts = 0; |
| 643 | completion_status = FLUSH_GIVEUP; | 655 | completion_status = FLUSH_GIVEUP; |
| 644 | break; | 656 | break; |
| @@ -648,9 +660,14 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 648 | (completion_status == FLUSH_RETRY_TIMEOUT)); | 660 | (completion_status == FLUSH_RETRY_TIMEOUT)); |
| 649 | time2 = get_cycles(); | 661 | time2 = get_cycles(); |
| 650 | 662 | ||
| 651 | if ((completion_status == FLUSH_COMPLETE) && (bcp->conseccompletes > 5) | 663 | bcp->plugged_tries = 0; |
| 652 | && (hmaster->max_concurrent < hmaster->max_concurrent_constant)) | 664 | bcp->timeout_tries = 0; |
| 653 | hmaster->max_concurrent++; | 665 | |
| 666 | if ((completion_status == FLUSH_COMPLETE) && | ||
| 667 | (bcp->conseccompletes > bcp->complete_threshold) && | ||
| 668 | (hmaster->max_bau_concurrent < | ||
| 669 | hmaster->max_bau_concurrent_constant)) | ||
| 670 | hmaster->max_bau_concurrent++; | ||
| 654 | 671 | ||
| 655 | /* | 672 | /* |
| 656 | * hold any cpu not timing out here; no other cpu currently held by | 673 | * hold any cpu not timing out here; no other cpu currently held by |
| @@ -661,9 +678,10 @@ const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, | |||
| 661 | atomic_dec(&hmaster->active_descriptor_count); | 678 | atomic_dec(&hmaster->active_descriptor_count); |
| 662 | 679 | ||
| 663 | /* guard against cycles wrap */ | 680 | /* guard against cycles wrap */ |
| 664 | if (time2 > time1) | 681 | if (time2 > time1) { |
| 665 | stat->s_time += (time2 - time1); | 682 | elapsed = time2 - time1; |
| 666 | else | 683 | stat->s_time += elapsed; |
| 684 | } else | ||
| 667 | stat->s_requestor--; /* don't count this one */ | 685 | stat->s_requestor--; /* don't count this one */ |
| 668 | if (completion_status == FLUSH_COMPLETE && try > 1) | 686 | if (completion_status == FLUSH_COMPLETE && try > 1) |
| 669 | stat->s_retriesok++; | 687 | stat->s_retriesok++; |
| @@ -730,10 +748,12 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | |||
| 730 | struct ptc_stats *stat; | 748 | struct ptc_stats *stat; |
| 731 | struct bau_control *bcp; | 749 | struct bau_control *bcp; |
| 732 | 750 | ||
| 751 | /* kernel was booted 'nobau' */ | ||
| 733 | if (nobau) | 752 | if (nobau) |
| 734 | return cpumask; | 753 | return cpumask; |
| 735 | 754 | ||
| 736 | bcp = &per_cpu(bau_control, cpu); | 755 | bcp = &per_cpu(bau_control, cpu); |
| 756 | |||
| 737 | /* | 757 | /* |
| 738 | * Each sending cpu has a per-cpu mask which it fills from the caller's | 758 | * Each sending cpu has a per-cpu mask which it fills from the caller's |
| 739 | * cpu mask. Only remote cpus are converted to uvhubs and copied. | 759 | * cpu mask. Only remote cpus are converted to uvhubs and copied. |
| @@ -970,6 +990,7 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data) | |||
| 970 | stat->s_resets_plug, stat->s_resets_timeout, | 990 | stat->s_resets_plug, stat->s_resets_timeout, |
| 971 | stat->s_giveup, stat->s_stimeout, | 991 | stat->s_giveup, stat->s_stimeout, |
| 972 | stat->s_busy, stat->s_throttles); | 992 | stat->s_busy, stat->s_throttles); |
| 993 | |||
| 973 | /* destination side statistics */ | 994 | /* destination side statistics */ |
| 974 | seq_printf(file, | 995 | seq_printf(file, |
| 975 | "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", | 996 | "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", |
| @@ -986,9 +1007,28 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data) | |||
| 986 | } | 1007 | } |
| 987 | 1008 | ||
| 988 | /* | 1009 | /* |
| 1010 | * Display the tunables thru debugfs | ||
| 1011 | */ | ||
| 1012 | static ssize_t tunables_read(struct file *file, char __user *userbuf, | ||
| 1013 | size_t count, loff_t *ppos) | ||
| 1014 | { | ||
| 1015 | char buf[300]; | ||
| 1016 | int ret; | ||
| 1017 | |||
| 1018 | ret = snprintf(buf, 300, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n", | ||
| 1019 | "max_bau_concurrent plugged_delay plugsb4reset", | ||
| 1020 | "timeoutsb4reset ipi_reset_limit complete_threshold", | ||
| 1021 | "congested_response_us congested_reps congested_period", | ||
| 1022 | max_bau_concurrent, plugged_delay, plugsb4reset, | ||
| 1023 | timeoutsb4reset, ipi_reset_limit, complete_threshold, | ||
| 1024 | congested_response_us, congested_reps, congested_period); | ||
| 1025 | |||
| 1026 | return simple_read_from_buffer(userbuf, count, ppos, buf, ret); | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | /* | ||
| 989 | * -1: resetf the statistics | 1030 | * -1: resetf the statistics |
| 990 | * 0: display meaning of the statistics | 1031 | * 0: display meaning of the statistics |
| 991 | * >0: maximum concurrent active descriptors per uvhub (throttle) | ||
| 992 | */ | 1032 | */ |
| 993 | static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user, | 1033 | static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user, |
| 994 | size_t count, loff_t *data) | 1034 | size_t count, loff_t *data) |
| @@ -997,7 +1037,6 @@ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user, | |||
| 997 | long input_arg; | 1037 | long input_arg; |
| 998 | char optstr[64]; | 1038 | char optstr[64]; |
| 999 | struct ptc_stats *stat; | 1039 | struct ptc_stats *stat; |
| 1000 | struct bau_control *bcp; | ||
| 1001 | 1040 | ||
| 1002 | if (count == 0 || count > sizeof(optstr)) | 1041 | if (count == 0 || count > sizeof(optstr)) |
| 1003 | return -EINVAL; | 1042 | return -EINVAL; |
| @@ -1078,24 +1117,149 @@ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user, | |||
| 1078 | stat = &per_cpu(ptcstats, cpu); | 1117 | stat = &per_cpu(ptcstats, cpu); |
| 1079 | memset(stat, 0, sizeof(struct ptc_stats)); | 1118 | memset(stat, 0, sizeof(struct ptc_stats)); |
| 1080 | } | 1119 | } |
| 1081 | } else { | 1120 | } |
| 1082 | uv_bau_max_concurrent = input_arg; | 1121 | |
| 1083 | bcp = &per_cpu(bau_control, smp_processor_id()); | 1122 | return count; |
| 1084 | if (uv_bau_max_concurrent < 1 || | 1123 | } |
| 1085 | uv_bau_max_concurrent > bcp->cpus_in_uvhub) { | 1124 | |
| 1086 | printk(KERN_DEBUG | 1125 | static int local_atoi(const char *name) |
| 1087 | "Error: BAU max concurrent %d; %d is invalid\n", | 1126 | { |
| 1088 | bcp->max_concurrent, uv_bau_max_concurrent); | 1127 | int val = 0; |
| 1089 | return -EINVAL; | 1128 | |
| 1090 | } | 1129 | for (;; name++) { |
| 1091 | printk(KERN_DEBUG "Set BAU max concurrent:%d\n", | 1130 | switch (*name) { |
| 1092 | uv_bau_max_concurrent); | 1131 | case '0' ... '9': |
| 1093 | for_each_present_cpu(cpu) { | 1132 | val = 10*val+(*name-'0'); |
| 1094 | bcp = &per_cpu(bau_control, cpu); | 1133 | break; |
| 1095 | bcp->max_concurrent = uv_bau_max_concurrent; | 1134 | default: |
| 1135 | return val; | ||
| 1096 | } | 1136 | } |
| 1097 | } | 1137 | } |
| 1138 | } | ||
| 1139 | |||
| 1140 | /* | ||
| 1141 | * set the tunables | ||
| 1142 | * 0 values reset them to defaults | ||
| 1143 | */ | ||
| 1144 | static ssize_t tunables_write(struct file *file, const char __user *user, | ||
| 1145 | size_t count, loff_t *data) | ||
| 1146 | { | ||
| 1147 | int cpu; | ||
| 1148 | int cnt = 0; | ||
| 1149 | int val; | ||
| 1150 | char *p; | ||
| 1151 | char *q; | ||
| 1152 | char instr[64]; | ||
| 1153 | struct bau_control *bcp; | ||
| 1098 | 1154 | ||
| 1155 | if (count == 0 || count > sizeof(instr)-1) | ||
| 1156 | return -EINVAL; | ||
| 1157 | if (copy_from_user(instr, user, count)) | ||
| 1158 | return -EFAULT; | ||
| 1159 | |||
| 1160 | instr[count] = '\0'; | ||
| 1161 | /* count the fields */ | ||
| 1162 | p = instr + strspn(instr, WHITESPACE); | ||
| 1163 | q = p; | ||
| 1164 | for (; *p; p = q + strspn(q, WHITESPACE)) { | ||
| 1165 | q = p + strcspn(p, WHITESPACE); | ||
| 1166 | cnt++; | ||
| 1167 | if (q == p) | ||
| 1168 | break; | ||
| 1169 | } | ||
| 1170 | if (cnt != 9) { | ||
| 1171 | printk(KERN_INFO "bau tunable error: should be 9 numbers\n"); | ||
| 1172 | return -EINVAL; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | p = instr + strspn(instr, WHITESPACE); | ||
| 1176 | q = p; | ||
| 1177 | for (cnt = 0; *p; p = q + strspn(q, WHITESPACE), cnt++) { | ||
| 1178 | q = p + strcspn(p, WHITESPACE); | ||
| 1179 | val = local_atoi(p); | ||
| 1180 | switch (cnt) { | ||
| 1181 | case 0: | ||
| 1182 | if (val == 0) { | ||
| 1183 | max_bau_concurrent = MAX_BAU_CONCURRENT; | ||
| 1184 | max_bau_concurrent_constant = | ||
| 1185 | MAX_BAU_CONCURRENT; | ||
| 1186 | continue; | ||
| 1187 | } | ||
| 1188 | bcp = &per_cpu(bau_control, smp_processor_id()); | ||
| 1189 | if (val < 1 || val > bcp->cpus_in_uvhub) { | ||
| 1190 | printk(KERN_DEBUG | ||
| 1191 | "Error: BAU max concurrent %d is invalid\n", | ||
| 1192 | val); | ||
| 1193 | return -EINVAL; | ||
| 1194 | } | ||
| 1195 | max_bau_concurrent = val; | ||
| 1196 | max_bau_concurrent_constant = val; | ||
| 1197 | continue; | ||
| 1198 | case 1: | ||
| 1199 | if (val == 0) | ||
| 1200 | plugged_delay = PLUGGED_DELAY; | ||
| 1201 | else | ||
| 1202 | plugged_delay = val; | ||
| 1203 | continue; | ||
| 1204 | case 2: | ||
| 1205 | if (val == 0) | ||
| 1206 | plugsb4reset = PLUGSB4RESET; | ||
| 1207 | else | ||
| 1208 | plugsb4reset = val; | ||
| 1209 | continue; | ||
| 1210 | case 3: | ||
| 1211 | if (val == 0) | ||
| 1212 | timeoutsb4reset = TIMEOUTSB4RESET; | ||
| 1213 | else | ||
| 1214 | timeoutsb4reset = val; | ||
| 1215 | continue; | ||
| 1216 | case 4: | ||
| 1217 | if (val == 0) | ||
| 1218 | ipi_reset_limit = IPI_RESET_LIMIT; | ||
| 1219 | else | ||
| 1220 | ipi_reset_limit = val; | ||
| 1221 | continue; | ||
| 1222 | case 5: | ||
| 1223 | if (val == 0) | ||
| 1224 | complete_threshold = COMPLETE_THRESHOLD; | ||
| 1225 | else | ||
| 1226 | complete_threshold = val; | ||
| 1227 | continue; | ||
| 1228 | case 6: | ||
| 1229 | if (val == 0) | ||
| 1230 | congested_response_us = CONGESTED_RESPONSE_US; | ||
| 1231 | else | ||
| 1232 | congested_response_us = val; | ||
| 1233 | continue; | ||
| 1234 | case 7: | ||
| 1235 | if (val == 0) | ||
| 1236 | congested_reps = CONGESTED_REPS; | ||
| 1237 | else | ||
| 1238 | congested_reps = val; | ||
| 1239 | continue; | ||
| 1240 | case 8: | ||
| 1241 | if (val == 0) | ||
| 1242 | congested_period = CONGESTED_PERIOD; | ||
| 1243 | else | ||
| 1244 | congested_period = val; | ||
| 1245 | continue; | ||
| 1246 | } | ||
| 1247 | if (q == p) | ||
| 1248 | break; | ||
| 1249 | } | ||
| 1250 | for_each_present_cpu(cpu) { | ||
| 1251 | bcp = &per_cpu(bau_control, cpu); | ||
| 1252 | bcp->max_bau_concurrent = max_bau_concurrent; | ||
| 1253 | bcp->max_bau_concurrent_constant = max_bau_concurrent; | ||
| 1254 | bcp->plugged_delay = plugged_delay; | ||
| 1255 | bcp->plugsb4reset = plugsb4reset; | ||
| 1256 | bcp->timeoutsb4reset = timeoutsb4reset; | ||
| 1257 | bcp->ipi_reset_limit = ipi_reset_limit; | ||
| 1258 | bcp->complete_threshold = complete_threshold; | ||
| 1259 | bcp->congested_response_us = congested_response_us; | ||
| 1260 | bcp->congested_reps = congested_reps; | ||
| 1261 | bcp->congested_period = congested_period; | ||
| 1262 | } | ||
| 1099 | return count; | 1263 | return count; |
| 1100 | } | 1264 | } |
| 1101 | 1265 | ||
| @@ -1111,6 +1275,11 @@ static int uv_ptc_proc_open(struct inode *inode, struct file *file) | |||
| 1111 | return seq_open(file, &uv_ptc_seq_ops); | 1275 | return seq_open(file, &uv_ptc_seq_ops); |
| 1112 | } | 1276 | } |
| 1113 | 1277 | ||
| 1278 | static int tunables_open(struct inode *inode, struct file *file) | ||
| 1279 | { | ||
| 1280 | return 0; | ||
| 1281 | } | ||
| 1282 | |||
| 1114 | static const struct file_operations proc_uv_ptc_operations = { | 1283 | static const struct file_operations proc_uv_ptc_operations = { |
| 1115 | .open = uv_ptc_proc_open, | 1284 | .open = uv_ptc_proc_open, |
| 1116 | .read = seq_read, | 1285 | .read = seq_read, |
| @@ -1119,6 +1288,12 @@ static const struct file_operations proc_uv_ptc_operations = { | |||
| 1119 | .release = seq_release, | 1288 | .release = seq_release, |
| 1120 | }; | 1289 | }; |
| 1121 | 1290 | ||
| 1291 | static const struct file_operations tunables_fops = { | ||
| 1292 | .open = tunables_open, | ||
| 1293 | .read = tunables_read, | ||
| 1294 | .write = tunables_write, | ||
| 1295 | }; | ||
| 1296 | |||
| 1122 | static int __init uv_ptc_init(void) | 1297 | static int __init uv_ptc_init(void) |
| 1123 | { | 1298 | { |
| 1124 | struct proc_dir_entry *proc_uv_ptc; | 1299 | struct proc_dir_entry *proc_uv_ptc; |
| @@ -1133,6 +1308,20 @@ static int __init uv_ptc_init(void) | |||
| 1133 | UV_PTC_BASENAME); | 1308 | UV_PTC_BASENAME); |
| 1134 | return -EINVAL; | 1309 | return -EINVAL; |
| 1135 | } | 1310 | } |
| 1311 | |||
| 1312 | tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL); | ||
| 1313 | if (!tunables_dir) { | ||
| 1314 | printk(KERN_ERR "unable to create debugfs directory %s\n", | ||
| 1315 | UV_BAU_TUNABLES_DIR); | ||
| 1316 | return -EINVAL; | ||
| 1317 | } | ||
| 1318 | tunables_file = debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600, | ||
| 1319 | tunables_dir, NULL, &tunables_fops); | ||
| 1320 | if (!tunables_file) { | ||
| 1321 | printk(KERN_ERR "unable to create debugfs file %s\n", | ||
| 1322 | UV_BAU_TUNABLES_FILE); | ||
| 1323 | return -EINVAL; | ||
| 1324 | } | ||
| 1136 | return 0; | 1325 | return 0; |
| 1137 | } | 1326 | } |
| 1138 | 1327 | ||
| @@ -1336,15 +1525,12 @@ static void uv_init_per_cpu(int nuvhubs) | |||
| 1336 | bcp = &per_cpu(bau_control, cpu); | 1525 | bcp = &per_cpu(bau_control, cpu); |
| 1337 | memset(bcp, 0, sizeof(struct bau_control)); | 1526 | memset(bcp, 0, sizeof(struct bau_control)); |
| 1338 | spin_lock_init(&bcp->masks_lock); | 1527 | spin_lock_init(&bcp->masks_lock); |
| 1339 | bcp->max_concurrent = uv_bau_max_concurrent; | ||
| 1340 | pnode = uv_cpu_hub_info(cpu)->pnode; | 1528 | pnode = uv_cpu_hub_info(cpu)->pnode; |
| 1341 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; | 1529 | uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; |
| 1342 | bdp = &uvhub_descs[uvhub]; | 1530 | bdp = &uvhub_descs[uvhub]; |
| 1343 | bdp->num_cpus++; | 1531 | bdp->num_cpus++; |
| 1344 | bdp->uvhub = uvhub; | 1532 | bdp->uvhub = uvhub; |
| 1345 | bdp->pnode = pnode; | 1533 | bdp->pnode = pnode; |
| 1346 | /* time interval to catch a hardware stay-busy bug */ | ||
| 1347 | bcp->timeout_interval = microsec_2_cycles(2*timeout_us); | ||
| 1348 | /* kludge: assume uv_hub.h is constant */ | 1534 | /* kludge: assume uv_hub.h is constant */ |
| 1349 | socket = (cpu_physical_id(cpu)>>5)&1; | 1535 | socket = (cpu_physical_id(cpu)>>5)&1; |
| 1350 | if (socket >= bdp->num_sockets) | 1536 | if (socket >= bdp->num_sockets) |
| @@ -1380,6 +1566,21 @@ static void uv_init_per_cpu(int nuvhubs) | |||
| 1380 | } | 1566 | } |
| 1381 | } | 1567 | } |
| 1382 | kfree(uvhub_descs); | 1568 | kfree(uvhub_descs); |
| 1569 | for_each_present_cpu(cpu) { | ||
| 1570 | bcp = &per_cpu(bau_control, cpu); | ||
| 1571 | /* time interval to catch a hardware stay-busy bug */ | ||
| 1572 | bcp->timeout_interval = microsec_2_cycles(2*timeout_us); | ||
| 1573 | bcp->max_bau_concurrent = max_bau_concurrent; | ||
| 1574 | bcp->max_bau_concurrent_constant = max_bau_concurrent; | ||
| 1575 | bcp->plugged_delay = plugged_delay; | ||
| 1576 | bcp->plugsb4reset = plugsb4reset; | ||
| 1577 | bcp->timeoutsb4reset = timeoutsb4reset; | ||
| 1578 | bcp->ipi_reset_limit = ipi_reset_limit; | ||
| 1579 | bcp->complete_threshold = complete_threshold; | ||
| 1580 | bcp->congested_response_us = congested_response_us; | ||
| 1581 | bcp->congested_reps = congested_reps; | ||
| 1582 | bcp->congested_period = congested_period; | ||
| 1583 | } | ||
| 1383 | } | 1584 | } |
| 1384 | 1585 | ||
| 1385 | /* | 1586 | /* |
| @@ -1404,7 +1605,7 @@ static int __init uv_bau_init(void) | |||
| 1404 | zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), | 1605 | zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), |
| 1405 | GFP_KERNEL, cpu_to_node(cur_cpu)); | 1606 | GFP_KERNEL, cpu_to_node(cur_cpu)); |
| 1406 | 1607 | ||
| 1407 | uv_bau_max_concurrent = MAX_BAU_CONCURRENT; | 1608 | max_bau_concurrent = MAX_BAU_CONCURRENT; |
| 1408 | uv_nshift = uv_hub_info->m_val; | 1609 | uv_nshift = uv_hub_info->m_val; |
| 1409 | uv_mmask = (1UL << uv_hub_info->m_val) - 1; | 1610 | uv_mmask = (1UL << uv_hub_info->m_val) - 1; |
| 1410 | nuvhubs = uv_num_possible_blades(); | 1611 | nuvhubs = uv_num_possible_blades(); |
| @@ -1437,4 +1638,4 @@ static int __init uv_bau_init(void) | |||
| 1437 | return 0; | 1638 | return 0; |
| 1438 | } | 1639 | } |
| 1439 | core_initcall(uv_bau_init); | 1640 | core_initcall(uv_bau_init); |
| 1440 | core_initcall(uv_ptc_init); | 1641 | fs_initcall(uv_ptc_init); |
