aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/mm/tsb.c21
-rw-r--r--kernel/sysctl.c14
2 files changed, 28 insertions, 7 deletions
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index f0282fad632a..36a0813f9517 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -265,6 +265,18 @@ void __init pgtable_cache_init(void)
265 } 265 }
266} 266}
267 267
268int sysctl_tsb_ratio = -2;
269
270static unsigned long tsb_size_to_rss_limit(unsigned long new_size)
271{
272 unsigned long num_ents = (new_size / sizeof(struct tsb));
273
274 if (sysctl_tsb_ratio < 0)
275 return num_ents - (num_ents >> -sysctl_tsb_ratio);
276 else
277 return num_ents + (num_ents >> sysctl_tsb_ratio);
278}
279
268/* When the RSS of an address space exceeds tsb_rss_limit for a TSB, 280/* When the RSS of an address space exceeds tsb_rss_limit for a TSB,
269 * do_sparc64_fault() invokes this routine to try and grow it. 281 * do_sparc64_fault() invokes this routine to try and grow it.
270 * 282 *
@@ -295,19 +307,14 @@ void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long rss)
295 307
296 new_cache_index = 0; 308 new_cache_index = 0;
297 for (new_size = 8192; new_size < max_tsb_size; new_size <<= 1UL) { 309 for (new_size = 8192; new_size < max_tsb_size; new_size <<= 1UL) {
298 unsigned long n_entries = new_size / sizeof(struct tsb); 310 new_rss_limit = tsb_size_to_rss_limit(new_size);
299 311 if (new_rss_limit > rss)
300 n_entries = (n_entries * 3) / 4;
301 if (n_entries > rss)
302 break; 312 break;
303
304 new_cache_index++; 313 new_cache_index++;
305 } 314 }
306 315
307 if (new_size == max_tsb_size) 316 if (new_size == max_tsb_size)
308 new_rss_limit = ~0UL; 317 new_rss_limit = ~0UL;
309 else
310 new_rss_limit = ((new_size / sizeof(struct tsb)) * 3) / 4;
311 318
312retry_tsb_alloc: 319retry_tsb_alloc:
313 gfp_flags = GFP_KERNEL; 320 gfp_flags = GFP_KERNEL;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3d56fe7570da..4e2ac0aec9b0 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -121,6 +121,10 @@ extern int sg_big_buff;
121#include <asm/system.h> 121#include <asm/system.h>
122#endif 122#endif
123 123
124#ifdef CONFIG_SPARC64
125extern int sysctl_tsb_ratio;
126#endif
127
124#ifdef __hppa__ 128#ifdef __hppa__
125extern int pwrsw_enabled; 129extern int pwrsw_enabled;
126extern int unaligned_enabled; 130extern int unaligned_enabled;
@@ -451,6 +455,16 @@ static struct ctl_table kern_table[] = {
451 .proc_handler = &proc_dointvec, 455 .proc_handler = &proc_dointvec,
452 }, 456 },
453#endif 457#endif
458#ifdef CONFIG_SPARC64
459 {
460 .ctl_name = CTL_UNNUMBERED,
461 .procname = "tsb-ratio",
462 .data = &sysctl_tsb_ratio,
463 .maxlen = sizeof (int),
464 .mode = 0644,
465 .proc_handler = &proc_dointvec,
466 },
467#endif
454#ifdef __hppa__ 468#ifdef __hppa__
455 { 469 {
456 .ctl_name = KERN_HPPA_PWRSW, 470 .ctl_name = KERN_HPPA_PWRSW,