Commit b1541be9 authored by Adam Kropelin's avatar Adam Kropelin Committed by Linus Torvalds

[PATCH] preset loops_per_jiffy for faster booting

Adds a kernel boot parameter "lpj=NNN" which allows the operator to specify
the loops-per-jiffy value.  This shaves up to a quarter of a second off
boot times, which are critical for embedded appliances.

It's a bit thin, but the code is in __init.
Signed-off-by: default avatarAdam Kropelin <akropel1@rochester.rr.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f2c2e878
...@@ -579,6 +579,20 @@ running once the system is up. ...@@ -579,6 +579,20 @@ running once the system is up.
so, the driver will manage that printer. so, the driver will manage that printer.
See also header of drivers/char/lp.c. See also header of drivers/char/lp.c.
lpj=n [KNL]
Sets loops_per_jiffy to given constant, thus avoiding
time-consuming boot-time autodetection (up to 250 ms per
CPU). 0 enables autodetection (default). To determine
the correct value for your kernel, boot with normal
autodetection and see what value is printed. Note that
on SMP systems the preset will be applied to all CPUs,
which is likely to cause problems if your CPUs need
significantly divergent settings. An incorrect value
will cause delays in the kernel to be wrong, leading to
unpredictable I/O errors and other breakage. Although
unlikely, in the extreme case this might damage your
hardware.
ltpc= [NET] ltpc= [NET]
Format: <io>,<irq>,<dma> Format: <io>,<irq>,<dma>
......
...@@ -184,15 +184,28 @@ static int __init obsolete_checksetup(char *line) ...@@ -184,15 +184,28 @@ static int __init obsolete_checksetup(char *line)
return 0; return 0;
} }
/* this should be approx 2 Bo*oMips to start (note initial shift), and will static unsigned long preset_lpj;
still work even if initially too large, it will just take slightly longer */ static int __init lpj_setup(char *str)
{
preset_lpj = simple_strtoul(str,NULL,0);
return 1;
}
__setup("lpj=", lpj_setup);
/*
* This should be approx 2 Bo*oMips to start (note initial shift), and will
* still work even if initially too large, it will just take slightly longer
*/
unsigned long loops_per_jiffy = (1<<12); unsigned long loops_per_jiffy = (1<<12);
EXPORT_SYMBOL(loops_per_jiffy); EXPORT_SYMBOL(loops_per_jiffy);
/* This is the number of bits of precision for the loops_per_jiffy. Each /*
bit takes on average 1.5/HZ seconds. This (like the original) is a little * This is the number of bits of precision for the loops_per_jiffy. Each
better than 1% */ * bit takes on average 1.5/HZ seconds. This (like the original) is a little
* better than 1%
*/
#define LPS_PREC 8 #define LPS_PREC 8
void __devinit calibrate_delay(void) void __devinit calibrate_delay(void)
...@@ -200,40 +213,53 @@ void __devinit calibrate_delay(void) ...@@ -200,40 +213,53 @@ void __devinit calibrate_delay(void)
unsigned long ticks, loopbit; unsigned long ticks, loopbit;
int lps_precision = LPS_PREC; int lps_precision = LPS_PREC;
loops_per_jiffy = (1<<12); if (preset_lpj) {
loops_per_jiffy = preset_lpj;
printk("Calibrating delay loop... "); printk("Calibrating delay loop (skipped)... "
while ((loops_per_jiffy <<= 1) != 0) { "%lu.%02lu BogoMIPS preset\n",
/* wait for "start of" clock tick */ loops_per_jiffy/(500000/HZ),
ticks = jiffies; (loops_per_jiffy/(5000/HZ)) % 100);
while (ticks == jiffies) } else {
/* nothing */; loops_per_jiffy = (1<<12);
/* Go .. */
ticks = jiffies; printk("Calibrating delay loop... ");
__delay(loops_per_jiffy); while ((loops_per_jiffy <<= 1) != 0) {
ticks = jiffies - ticks; /* wait for "start of" clock tick */
if (ticks) ticks = jiffies;
break; while (ticks == jiffies)
} /* nothing */;
/* Go .. */
ticks = jiffies;
__delay(loops_per_jiffy);
ticks = jiffies - ticks;
if (ticks)
break;
}
/*
* Do a binary approximation to get loops_per_jiffy set to
* equal one clock (up to lps_precision bits)
*/
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit;
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
ticks = jiffies;
__delay(loops_per_jiffy);
if (jiffies != ticks) /* longer than 1 tick */
loops_per_jiffy &= ~loopbit;
}
/* Do a binary approximation to get loops_per_jiffy set to equal one clock /* Round the value and print it */
(up to lps_precision bits) */ printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
loops_per_jiffy >>= 1; loops_per_jiffy/(500000/HZ),
loopbit = loops_per_jiffy; (loops_per_jiffy/(5000/HZ)) % 100,
while ( lps_precision-- && (loopbit >>= 1) ) { loops_per_jiffy);
loops_per_jiffy |= loopbit;
ticks = jiffies;
while (ticks == jiffies);
ticks = jiffies;
__delay(loops_per_jiffy);
if (jiffies != ticks) /* longer than 1 tick */
loops_per_jiffy &= ~loopbit;
} }
/* Round the value and print it */
printk("%lu.%02lu BogoMIPS\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
} }
static int __init debug_kernel(char *str) static int __init debug_kernel(char *str)
...@@ -255,8 +281,10 @@ static int __init quiet_kernel(char *str) ...@@ -255,8 +281,10 @@ static int __init quiet_kernel(char *str)
__setup("debug", debug_kernel); __setup("debug", debug_kernel);
__setup("quiet", quiet_kernel); __setup("quiet", quiet_kernel);
/* Unknown boot options get handed to init, unless they look like /*
failed parameters */ * Unknown boot options get handed to init, unless they look like
* failed parameters
*/
static int __init unknown_bootoption(char *param, char *val) static int __init unknown_bootoption(char *param, char *val)
{ {
/* Change NUL term back to "=", to make "param" the whole string. */ /* Change NUL term back to "=", to make "param" the whole string. */
...@@ -267,8 +295,10 @@ static int __init unknown_bootoption(char *param, char *val) ...@@ -267,8 +295,10 @@ static int __init unknown_bootoption(char *param, char *val)
if (obsolete_checksetup(param)) if (obsolete_checksetup(param))
return 0; return 0;
/* Preemptive maintenance for "why didn't my mispelled command /*
line work?" */ * Preemptive maintenance for "why didn't my mispelled command
* line work?"
*/
if (strchr(param, '.') && (!val || strchr(param, '.') < val)) { if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param); printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
return 0; return 0;
...@@ -308,7 +338,8 @@ static int __init init_setup(char *str) ...@@ -308,7 +338,8 @@ static int __init init_setup(char *str)
unsigned int i; unsigned int i;
execute_command = str; execute_command = str;
/* In case LILO is going to boot us with default command line, /*
* In case LILO is going to boot us with default command line,
* it prepends "auto" before the whole cmdline which makes * it prepends "auto" before the whole cmdline which makes
* the shell think it should execute a script with such name. * the shell think it should execute a script with such name.
* So we ignore all arguments entered _before_ init=... [MJ] * So we ignore all arguments entered _before_ init=... [MJ]
......
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