aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-11-07 03:59:56 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:44 -0500
commitc4edff1c19ef23e15aae64ca03f32c6719822d54 (patch)
tree06858fc7330b433b629827347c63ad890c715b3e /drivers/char
parent393d2cc354d150b8b4bb888a9da7db4c935e12bd (diff)
[PATCH] ipmi: various si cleanup
A number of small changes for the various system interface drivers, consolidated from a number of patches from Matt Domsch. Clear B2H_ATN and drain the BMC message buffer on command timeout. This prevents further commands from failing after a timeout. Add bt_debug and smic_debug module parameters, expose them in sysfs. This lets you enable and disable debugging messages at runtime. Unsigned jiffies math in ipmi_si_intf.c causes a too-large value to be passed to ->event() after jiffies wrap-around. The BT driver had caught this, but didn't know how to fix it. Now all calls to ->event() use a sane value for time. Increase timeout for commands handed to the BT driver from 2 seconds to 5 seconds. This is necessary particularly when the previous command was a "Clear SEL", as that command completes, yet the BMC isn't really ready to handle another command yet. Silence BT debugging messages which were being printed on the console. Increase SMIC timeout form 1/10s to 2s. This is needed on Dell PowerEdge 2650 and PowerEdge 750 with ERA/O cards to allow commands to complete without timing out. Adds kcs_debug module param, to match behavior of BT and SMIC. This also prevents messages from being sent to the console unless explicitly requested. Signed-off-by: Matt Domsch <Matt_Domsch@dell.com> Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c34
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c40
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c4
-rw-r--r--drivers/char/ipmi/ipmi_smic_sm.c6
4 files changed, 47 insertions, 37 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 33862670e285..7c4a195dfc9a 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -28,6 +28,8 @@
28 28
29#include <linux/kernel.h> /* For printk. */ 29#include <linux/kernel.h> /* For printk. */
30#include <linux/string.h> 30#include <linux/string.h>
31#include <linux/module.h>
32#include <linux/moduleparam.h>
31#include <linux/ipmi_msgdefs.h> /* for completion codes */ 33#include <linux/ipmi_msgdefs.h> /* for completion codes */
32#include "ipmi_si_sm.h" 34#include "ipmi_si_sm.h"
33 35
@@ -36,6 +38,8 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */
36#define BT_DEBUG_ENABLE 1 38#define BT_DEBUG_ENABLE 1
37#define BT_DEBUG_MSG 2 39#define BT_DEBUG_MSG 2
38#define BT_DEBUG_STATES 4 40#define BT_DEBUG_STATES 4
41module_param(bt_debug, int, 0644);
42MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
39 43
40/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds, 44/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
41 and 64 byte buffers. However, one HP implementation wants 255 bytes of 45 and 64 byte buffers. However, one HP implementation wants 255 bytes of
@@ -43,7 +47,7 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */
43 Since the Open IPMI architecture is single-message oriented at this 47 Since the Open IPMI architecture is single-message oriented at this
44 stage, the queue depth of BT is of no concern. */ 48 stage, the queue depth of BT is of no concern. */
45 49
46#define BT_NORMAL_TIMEOUT 2000000 /* seconds in microseconds */ 50#define BT_NORMAL_TIMEOUT 5000000 /* seconds in microseconds */
47#define BT_RETRY_LIMIT 2 51#define BT_RETRY_LIMIT 2
48#define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */ 52#define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */
49 53
@@ -202,7 +206,7 @@ static int bt_get_result(struct si_sm_data *bt,
202 msg_len = bt->read_count - 2; /* account for length & seq */ 206 msg_len = bt->read_count - 2; /* account for length & seq */
203 /* Always NetFn, Cmd, cCode */ 207 /* Always NetFn, Cmd, cCode */
204 if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) { 208 if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) {
205 printk(KERN_WARNING "BT results: bad msg_len = %d\n", msg_len); 209 printk(KERN_DEBUG "BT results: bad msg_len = %d\n", msg_len);
206 data[0] = bt->write_data[1] | 0x4; /* Kludge a response */ 210 data[0] = bt->write_data[1] | 0x4; /* Kludge a response */
207 data[1] = bt->write_data[3]; 211 data[1] = bt->write_data[3];
208 data[2] = IPMI_ERR_UNSPECIFIED; 212 data[2] = IPMI_ERR_UNSPECIFIED;
@@ -240,7 +244,7 @@ static void reset_flags(struct si_sm_data *bt)
240 BT_CONTROL(BT_B_BUSY); 244 BT_CONTROL(BT_B_BUSY);
241 BT_CONTROL(BT_CLR_WR_PTR); 245 BT_CONTROL(BT_CLR_WR_PTR);
242 BT_CONTROL(BT_SMS_ATN); 246 BT_CONTROL(BT_SMS_ATN);
243#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION 247
244 if (BT_STATUS & BT_B2H_ATN) { 248 if (BT_STATUS & BT_B2H_ATN) {
245 int i; 249 int i;
246 BT_CONTROL(BT_H_BUSY); 250 BT_CONTROL(BT_H_BUSY);
@@ -250,7 +254,6 @@ static void reset_flags(struct si_sm_data *bt)
250 BMC2HOST; 254 BMC2HOST;
251 BT_CONTROL(BT_H_BUSY); 255 BT_CONTROL(BT_H_BUSY);
252 } 256 }
253#endif
254} 257}
255 258
256static inline void write_all_bytes(struct si_sm_data *bt) 259static inline void write_all_bytes(struct si_sm_data *bt)
@@ -295,7 +298,7 @@ static inline int read_all_bytes(struct si_sm_data *bt)
295 printk ("\n"); 298 printk ("\n");
296 } 299 }
297 if (bt->seq != bt->write_data[2]) /* idiot check */ 300 if (bt->seq != bt->write_data[2]) /* idiot check */
298 printk(KERN_WARNING "BT: internal error: sequence mismatch\n"); 301 printk(KERN_DEBUG "BT: internal error: sequence mismatch\n");
299 302
300 /* per the spec, the (NetFn, Seq, Cmd) tuples should match */ 303 /* per the spec, the (NetFn, Seq, Cmd) tuples should match */
301 if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */ 304 if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */
@@ -321,18 +324,18 @@ static void error_recovery(struct si_sm_data *bt, char *reason)
321 bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */ 324 bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */
322 325
323 status = BT_STATUS; 326 status = BT_STATUS;
324 printk(KERN_WARNING "BT: %s in %s %s ", reason, STATE2TXT, 327 printk(KERN_DEBUG "BT: %s in %s %s\n", reason, STATE2TXT,
325 STATUS2TXT(buf)); 328 STATUS2TXT(buf));
326 329
327 (bt->error_retries)++; 330 (bt->error_retries)++;
328 if (bt->error_retries > BT_RETRY_LIMIT) { 331 if (bt->error_retries > BT_RETRY_LIMIT) {
329 printk("retry limit (%d) exceeded\n", BT_RETRY_LIMIT); 332 printk(KERN_DEBUG "retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
330 bt->state = BT_STATE_HOSED; 333 bt->state = BT_STATE_HOSED;
331 if (!bt->nonzero_status) 334 if (!bt->nonzero_status)
332 printk(KERN_ERR "IPMI: BT stuck, try power cycle\n"); 335 printk(KERN_ERR "IPMI: BT stuck, try power cycle\n");
333 else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) { 336 else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) {
334 /* most likely during insmod */ 337 /* most likely during insmod */
335 printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n"); 338 printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n");
336 bt->state = BT_STATE_RESET1; 339 bt->state = BT_STATE_RESET1;
337 } 340 }
338 return; 341 return;
@@ -340,11 +343,11 @@ static void error_recovery(struct si_sm_data *bt, char *reason)
340 343
341 /* Sometimes the BMC queues get in an "off-by-one" state...*/ 344 /* Sometimes the BMC queues get in an "off-by-one" state...*/
342 if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) { 345 if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) {
343 printk("retry B2H_WAIT\n"); 346 printk(KERN_DEBUG "retry B2H_WAIT\n");
344 return; 347 return;
345 } 348 }
346 349
347 printk("restart command\n"); 350 printk(KERN_DEBUG "restart command\n");
348 bt->state = BT_STATE_RESTART; 351 bt->state = BT_STATE_RESTART;
349} 352}
350 353
@@ -372,17 +375,6 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
372 return SI_SM_HOSED; 375 return SI_SM_HOSED;
373 376
374 if (bt->state != BT_STATE_IDLE) { /* do timeout test */ 377 if (bt->state != BT_STATE_IDLE) { /* do timeout test */
375
376 /* Certain states, on error conditions, can lock up a CPU
377 because they are effectively in an infinite loop with
378 CALL_WITHOUT_DELAY (right back here with time == 0).
379 Prevent infinite lockup by ALWAYS decrementing timeout. */
380
381 /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
382 (noticed in ipmi_smic_sm.c January 2004) */
383
384 if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
385 time = 100;
386 bt->timeout -= time; 378 bt->timeout -= time;
387 if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { 379 if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
388 error_recovery(bt, "timed out"); 380 error_recovery(bt, "timed out");
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index d21853a594a3..dc83365ede4a 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -38,16 +38,24 @@
38 */ 38 */
39 39
40#include <linux/kernel.h> /* For printk. */ 40#include <linux/kernel.h> /* For printk. */
41#include <linux/module.h>
42#include <linux/moduleparam.h>
41#include <linux/string.h> 43#include <linux/string.h>
42#include <linux/ipmi_msgdefs.h> /* for completion codes */ 44#include <linux/ipmi_msgdefs.h> /* for completion codes */
43#include "ipmi_si_sm.h" 45#include "ipmi_si_sm.h"
44 46
45/* Set this if you want a printout of why the state machine was hosed 47/* kcs_debug is a bit-field
46 when it gets hosed. */ 48 * KCS_DEBUG_ENABLE - turned on for now
47#define DEBUG_HOSED_REASON 49 * KCS_DEBUG_MSG - commands and their responses
50 * KCS_DEBUG_STATES - state machine
51 */
52#define KCS_DEBUG_STATES 4
53#define KCS_DEBUG_MSG 2
54#define KCS_DEBUG_ENABLE 1
48 55
49/* Print the state machine state on entry every time. */ 56static int kcs_debug;
50#undef DEBUG_STATE 57module_param(kcs_debug, int, 0644);
58MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
51 59
52/* The states the KCS driver may be in. */ 60/* The states the KCS driver may be in. */
53enum kcs_states { 61enum kcs_states {
@@ -175,9 +183,8 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
175{ 183{
176 (kcs->error_retries)++; 184 (kcs->error_retries)++;
177 if (kcs->error_retries > MAX_ERROR_RETRIES) { 185 if (kcs->error_retries > MAX_ERROR_RETRIES) {
178#ifdef DEBUG_HOSED_REASON 186 if (kcs_debug & KCS_DEBUG_ENABLE)
179 printk("ipmi_kcs_sm: kcs hosed: %s\n", reason); 187 printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason);
180#endif
181 kcs->state = KCS_HOSED; 188 kcs->state = KCS_HOSED;
182 } else { 189 } else {
183 kcs->state = KCS_ERROR0; 190 kcs->state = KCS_ERROR0;
@@ -248,14 +255,21 @@ static void restart_kcs_transaction(struct si_sm_data *kcs)
248static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data, 255static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
249 unsigned int size) 256 unsigned int size)
250{ 257{
258 unsigned int i;
259
251 if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) { 260 if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
252 return -1; 261 return -1;
253 } 262 }
254
255 if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) { 263 if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
256 return -2; 264 return -2;
257 } 265 }
258 266 if (kcs_debug & KCS_DEBUG_MSG) {
267 printk(KERN_DEBUG "start_kcs_transaction -");
268 for (i = 0; i < size; i ++) {
269 printk(" %02x", (unsigned char) (data [i]));
270 }
271 printk ("\n");
272 }
259 kcs->error_retries = 0; 273 kcs->error_retries = 0;
260 memcpy(kcs->write_data, data, size); 274 memcpy(kcs->write_data, data, size);
261 kcs->write_count = size; 275 kcs->write_count = size;
@@ -305,9 +319,9 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
305 319
306 status = read_status(kcs); 320 status = read_status(kcs);
307 321
308#ifdef DEBUG_STATE 322 if (kcs_debug & KCS_DEBUG_STATES)
309 printk(" State = %d, %x\n", kcs->state, status); 323 printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);
310#endif 324
311 /* All states wait for ibf, so just do it here. */ 325 /* All states wait for ibf, so just do it here. */
312 if (!check_ibf(kcs, status, time)) 326 if (!check_ibf(kcs, status, time))
313 return SI_SM_CALL_WITH_DELAY; 327 return SI_SM_CALL_WITH_DELAY;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index b6e5cbfb09f8..204e2e987e90 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -819,7 +819,7 @@ static void smi_timeout(unsigned long data)
819 enum si_sm_result smi_result; 819 enum si_sm_result smi_result;
820 unsigned long flags; 820 unsigned long flags;
821 unsigned long jiffies_now; 821 unsigned long jiffies_now;
822 unsigned long time_diff; 822 long time_diff;
823#ifdef DEBUG_TIMING 823#ifdef DEBUG_TIMING
824 struct timeval t; 824 struct timeval t;
825#endif 825#endif
@@ -835,7 +835,7 @@ static void smi_timeout(unsigned long data)
835 printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec); 835 printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
836#endif 836#endif
837 jiffies_now = jiffies; 837 jiffies_now = jiffies;
838 time_diff = ((jiffies_now - smi_info->last_timeout_jiffies) 838 time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
839 * SI_USEC_PER_JIFFY); 839 * SI_USEC_PER_JIFFY);
840 smi_result = smi_event_handler(smi_info, time_diff); 840 smi_result = smi_event_handler(smi_info, time_diff);
841 841
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
index add2aa2732f0..f17043da9dd5 100644
--- a/drivers/char/ipmi/ipmi_smic_sm.c
+++ b/drivers/char/ipmi/ipmi_smic_sm.c
@@ -43,6 +43,8 @@
43 43
44#include <linux/kernel.h> /* For printk. */ 44#include <linux/kernel.h> /* For printk. */
45#include <linux/string.h> 45#include <linux/string.h>
46#include <linux/module.h>
47#include <linux/moduleparam.h>
46#include <linux/ipmi_msgdefs.h> /* for completion codes */ 48#include <linux/ipmi_msgdefs.h> /* for completion codes */
47#include "ipmi_si_sm.h" 49#include "ipmi_si_sm.h"
48 50
@@ -56,6 +58,8 @@
56#define SMIC_DEBUG_ENABLE 1 58#define SMIC_DEBUG_ENABLE 1
57 59
58static int smic_debug = 1; 60static int smic_debug = 1;
61module_param(smic_debug, int, 0644);
62MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
59 63
60enum smic_states { 64enum smic_states {
61 SMIC_IDLE, 65 SMIC_IDLE,
@@ -76,7 +80,7 @@ enum smic_states {
76#define SMIC_MAX_ERROR_RETRIES 3 80#define SMIC_MAX_ERROR_RETRIES 3
77 81
78/* Timeouts in microseconds. */ 82/* Timeouts in microseconds. */
79#define SMIC_RETRY_TIMEOUT 100000 83#define SMIC_RETRY_TIMEOUT 2000000
80 84
81/* SMIC Flags Register Bits */ 85/* SMIC Flags Register Bits */
82#define SMIC_RX_DATA_READY 0x80 86#define SMIC_RX_DATA_READY 0x80