diff options
| author | Martin Wilck <martin.wilck@ts.fujitsu.com> | 2010-03-10 18:23:06 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-12 18:52:39 -0500 |
| commit | ae74e823cb7d4cd476f623fce9a38f625f6c09a8 (patch) | |
| tree | 404aba91d5c634cfc8d3ecc847281f12fc8e5e1e /drivers/char | |
| parent | f1eb1332b8f07e937add24c6fd2ac40b8737a2f4 (diff) | |
ipmi: add parameter to limit CPU usage in kipmid
In some cases kipmid can use a lot of CPU. This adds a way to tune the
CPU used by kipmid to help in those cases. By setting kipmid_max_busy_us
to a value between 100 and 500, it is possible to bring down kipmid CPU
load to practically 0 without loosing too much ipmi throughput
performance. Not setting the value, or setting the value to zero,
operation is unaffected.
Signed-off-by: Martin Wilck <martin.wilck@ts.fujitsu.com>
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Cc: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
| -rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 176f1751237f..c234ada64565 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -295,6 +295,9 @@ struct smi_info { | |||
| 295 | static int force_kipmid[SI_MAX_PARMS]; | 295 | static int force_kipmid[SI_MAX_PARMS]; |
| 296 | static int num_force_kipmid; | 296 | static int num_force_kipmid; |
| 297 | 297 | ||
| 298 | static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; | ||
| 299 | static int num_max_busy_us; | ||
| 300 | |||
| 298 | static int unload_when_empty = 1; | 301 | static int unload_when_empty = 1; |
| 299 | 302 | ||
| 300 | static int try_smi_init(struct smi_info *smi); | 303 | static int try_smi_init(struct smi_info *smi); |
| @@ -925,23 +928,77 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion) | |||
| 925 | } | 928 | } |
| 926 | } | 929 | } |
| 927 | 930 | ||
| 931 | /* | ||
| 932 | * Use -1 in the nsec value of the busy waiting timespec to tell that | ||
| 933 | * we are spinning in kipmid looking for something and not delaying | ||
| 934 | * between checks | ||
| 935 | */ | ||
| 936 | static inline void ipmi_si_set_not_busy(struct timespec *ts) | ||
| 937 | { | ||
| 938 | ts->tv_nsec = -1; | ||
| 939 | } | ||
| 940 | static inline int ipmi_si_is_busy(struct timespec *ts) | ||
| 941 | { | ||
| 942 | return ts->tv_nsec != -1; | ||
| 943 | } | ||
| 944 | |||
| 945 | static int ipmi_thread_busy_wait(enum si_sm_result smi_result, | ||
| 946 | const struct smi_info *smi_info, | ||
| 947 | struct timespec *busy_until) | ||
| 948 | { | ||
| 949 | unsigned int max_busy_us = 0; | ||
| 950 | |||
| 951 | if (smi_info->intf_num < num_max_busy_us) | ||
| 952 | max_busy_us = kipmid_max_busy_us[smi_info->intf_num]; | ||
| 953 | if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY) | ||
| 954 | ipmi_si_set_not_busy(busy_until); | ||
| 955 | else if (!ipmi_si_is_busy(busy_until)) { | ||
| 956 | getnstimeofday(busy_until); | ||
| 957 | timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC); | ||
| 958 | } else { | ||
| 959 | struct timespec now; | ||
| 960 | getnstimeofday(&now); | ||
| 961 | if (unlikely(timespec_compare(&now, busy_until) > 0)) { | ||
| 962 | ipmi_si_set_not_busy(busy_until); | ||
| 963 | return 0; | ||
| 964 | } | ||
| 965 | } | ||
| 966 | return 1; | ||
| 967 | } | ||
| 968 | |||
| 969 | |||
| 970 | /* | ||
| 971 | * A busy-waiting loop for speeding up IPMI operation. | ||
| 972 | * | ||
| 973 | * Lousy hardware makes this hard. This is only enabled for systems | ||
| 974 | * that are not BT and do not have interrupts. It starts spinning | ||
| 975 | * when an operation is complete or until max_busy tells it to stop | ||
| 976 | * (if that is enabled). See the paragraph on kimid_max_busy_us in | ||
| 977 | * Documentation/IPMI.txt for details. | ||
| 978 | */ | ||
| 928 | static int ipmi_thread(void *data) | 979 | static int ipmi_thread(void *data) |
| 929 | { | 980 | { |
| 930 | struct smi_info *smi_info = data; | 981 | struct smi_info *smi_info = data; |
| 931 | unsigned long flags; | 982 | unsigned long flags; |
| 932 | enum si_sm_result smi_result; | 983 | enum si_sm_result smi_result; |
| 984 | struct timespec busy_until; | ||
| 933 | 985 | ||
| 986 | ipmi_si_set_not_busy(&busy_until); | ||
| 934 | set_user_nice(current, 19); | 987 | set_user_nice(current, 19); |
| 935 | while (!kthread_should_stop()) { | 988 | while (!kthread_should_stop()) { |
| 989 | int busy_wait; | ||
| 990 | |||
| 936 | spin_lock_irqsave(&(smi_info->si_lock), flags); | 991 | spin_lock_irqsave(&(smi_info->si_lock), flags); |
| 937 | smi_result = smi_event_handler(smi_info, 0); | 992 | smi_result = smi_event_handler(smi_info, 0); |
| 938 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); | 993 | spin_unlock_irqrestore(&(smi_info->si_lock), flags); |
| 994 | busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, | ||
| 995 | &busy_until); | ||
| 939 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) | 996 | if (smi_result == SI_SM_CALL_WITHOUT_DELAY) |
| 940 | ; /* do nothing */ | 997 | ; /* do nothing */ |
| 941 | else if (smi_result == SI_SM_CALL_WITH_DELAY) | 998 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) |
| 942 | schedule(); | 999 | schedule(); |
| 943 | else | 1000 | else |
| 944 | schedule_timeout_interruptible(1); | 1001 | schedule_timeout_interruptible(0); |
| 945 | } | 1002 | } |
| 946 | return 0; | 1003 | return 0; |
| 947 | } | 1004 | } |
| @@ -1212,6 +1269,11 @@ module_param(unload_when_empty, int, 0); | |||
| 1212 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" | 1269 | MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" |
| 1213 | " specified or found, default is 1. Setting to 0" | 1270 | " specified or found, default is 1. Setting to 0" |
| 1214 | " is useful for hot add of devices using hotmod."); | 1271 | " is useful for hot add of devices using hotmod."); |
| 1272 | module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644); | ||
| 1273 | MODULE_PARM_DESC(kipmid_max_busy_us, | ||
| 1274 | "Max time (in microseconds) to busy-wait for IPMI data before" | ||
| 1275 | " sleeping. 0 (default) means to wait forever. Set to 100-500" | ||
| 1276 | " if kipmid is using up a lot of CPU time."); | ||
| 1215 | 1277 | ||
| 1216 | 1278 | ||
| 1217 | static void std_irq_cleanup(struct smi_info *info) | 1279 | static void std_irq_cleanup(struct smi_info *info) |
