aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorMartin Wilck <martin.wilck@ts.fujitsu.com>2010-03-10 18:23:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 18:52:39 -0500
commitae74e823cb7d4cd476f623fce9a38f625f6c09a8 (patch)
tree404aba91d5c634cfc8d3ecc847281f12fc8e5e1e /drivers/char
parentf1eb1332b8f07e937add24c6fd2ac40b8737a2f4 (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.c66
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 {
295static int force_kipmid[SI_MAX_PARMS]; 295static int force_kipmid[SI_MAX_PARMS];
296static int num_force_kipmid; 296static int num_force_kipmid;
297 297
298static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
299static int num_max_busy_us;
300
298static int unload_when_empty = 1; 301static int unload_when_empty = 1;
299 302
300static int try_smi_init(struct smi_info *smi); 303static 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 */
936static inline void ipmi_si_set_not_busy(struct timespec *ts)
937{
938 ts->tv_nsec = -1;
939}
940static inline int ipmi_si_is_busy(struct timespec *ts)
941{
942 return ts->tv_nsec != -1;
943}
944
945static 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 */
928static int ipmi_thread(void *data) 979static 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);
1212MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" 1269MODULE_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.");
1272module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644);
1273MODULE_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
1217static void std_irq_cleanup(struct smi_info *info) 1279static void std_irq_cleanup(struct smi_info *info)