diff options
author | Len Brown <len.brown@intel.com> | 2005-09-08 01:45:47 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-09-08 01:45:47 -0400 |
commit | 64e47488c913ac704d465a6af86a26786d1412a5 (patch) | |
tree | d3b0148592963dcde26e4bb35ddfec8b1eaf8e23 /drivers/char/ipmi | |
parent | 4a35a46bf1cda4737c428380d1db5d15e2590d18 (diff) | |
parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) |
Merge linux-2.6 with linux-acpi-2.6
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r-- | drivers/char/ipmi/ipmi_bt_sm.c | 69 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_devintf.c | 101 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_kcs_sm.c | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 336 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_poweroff.c | 168 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 395 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_smic_sm.c | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 46 |
8 files changed, 648 insertions, 473 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 5ce9c6269033..33862670e285 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
32 | #include "ipmi_si_sm.h" | 32 | #include "ipmi_si_sm.h" |
33 | 33 | ||
34 | #define IPMI_BT_VERSION "v33" | ||
35 | |||
36 | static int bt_debug = 0x00; /* Production value 0, see following flags */ | 34 | static int bt_debug = 0x00; /* Production value 0, see following flags */ |
37 | 35 | ||
38 | #define BT_DEBUG_ENABLE 1 | 36 | #define BT_DEBUG_ENABLE 1 |
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
163 | { | 161 | { |
164 | unsigned int i; | 162 | unsigned int i; |
165 | 163 | ||
166 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1; | 164 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) |
165 | return -1; | ||
167 | 166 | ||
168 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) | 167 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) |
169 | return -2; | 168 | return -2; |
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
171 | if (bt_debug & BT_DEBUG_MSG) { | 170 | if (bt_debug & BT_DEBUG_MSG) { |
172 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); | 171 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); |
173 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); | 172 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); |
174 | for (i = 0; i < size; i ++) printk (" %02x", data[i]); | 173 | for (i = 0; i < size; i ++) |
174 | printk (" %02x", data[i]); | ||
175 | printk("\n"); | 175 | printk("\n"); |
176 | } | 176 | } |
177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ | 177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ |
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt, | |||
210 | } else { | 210 | } else { |
211 | data[0] = bt->read_data[1]; | 211 | data[0] = bt->read_data[1]; |
212 | data[1] = bt->read_data[3]; | 212 | data[1] = bt->read_data[3]; |
213 | if (length < msg_len) bt->truncated = 1; | 213 | if (length < msg_len) |
214 | bt->truncated = 1; | ||
214 | if (bt->truncated) { /* can be set in read_all_bytes() */ | 215 | if (bt->truncated) { /* can be set in read_all_bytes() */ |
215 | data[2] = IPMI_ERR_MSG_TRUNCATED; | 216 | data[2] = IPMI_ERR_MSG_TRUNCATED; |
216 | msg_len = 3; | 217 | msg_len = 3; |
217 | } else memcpy(data + 2, bt->read_data + 4, msg_len - 2); | 218 | } else |
219 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); | ||
218 | 220 | ||
219 | if (bt_debug & BT_DEBUG_MSG) { | 221 | if (bt_debug & BT_DEBUG_MSG) { |
220 | printk (KERN_WARNING "BT: res (raw)"); | 222 | printk (KERN_WARNING "BT: res (raw)"); |
221 | for (i = 0; i < msg_len; i++) printk(" %02x", data[i]); | 223 | for (i = 0; i < msg_len; i++) |
224 | printk(" %02x", data[i]); | ||
222 | printk ("\n"); | 225 | printk ("\n"); |
223 | } | 226 | } |
224 | } | 227 | } |
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt, | |||
231 | 234 | ||
232 | static void reset_flags(struct si_sm_data *bt) | 235 | static void reset_flags(struct si_sm_data *bt) |
233 | { | 236 | { |
234 | if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY); | 237 | if (BT_STATUS & BT_H_BUSY) |
235 | if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY); | 238 | BT_CONTROL(BT_H_BUSY); |
239 | if (BT_STATUS & BT_B_BUSY) | ||
240 | BT_CONTROL(BT_B_BUSY); | ||
236 | BT_CONTROL(BT_CLR_WR_PTR); | 241 | BT_CONTROL(BT_CLR_WR_PTR); |
237 | BT_CONTROL(BT_SMS_ATN); | 242 | BT_CONTROL(BT_SMS_ATN); |
238 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION | 243 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION |
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt) | |||
241 | BT_CONTROL(BT_H_BUSY); | 246 | BT_CONTROL(BT_H_BUSY); |
242 | BT_CONTROL(BT_B2H_ATN); | 247 | BT_CONTROL(BT_B2H_ATN); |
243 | BT_CONTROL(BT_CLR_RD_PTR); | 248 | BT_CONTROL(BT_CLR_RD_PTR); |
244 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST; | 249 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) |
250 | BMC2HOST; | ||
245 | BT_CONTROL(BT_H_BUSY); | 251 | BT_CONTROL(BT_H_BUSY); |
246 | } | 252 | } |
247 | #endif | 253 | #endif |
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) | |||
258 | printk (" %02x", bt->write_data[i]); | 264 | printk (" %02x", bt->write_data[i]); |
259 | printk ("\n"); | 265 | printk ("\n"); |
260 | } | 266 | } |
261 | for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]); | 267 | for (i = 0; i < bt->write_count; i++) |
268 | HOST2BMC(bt->write_data[i]); | ||
262 | } | 269 | } |
263 | 270 | ||
264 | static inline int read_all_bytes(struct si_sm_data *bt) | 271 | static inline int read_all_bytes(struct si_sm_data *bt) |
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
278 | bt->truncated = 1; | 285 | bt->truncated = 1; |
279 | return 1; /* let next XACTION START clean it up */ | 286 | return 1; /* let next XACTION START clean it up */ |
280 | } | 287 | } |
281 | for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST; | 288 | for (i = 1; i <= bt->read_count; i++) |
289 | bt->read_data[i] = BMC2HOST; | ||
282 | bt->read_count++; /* account for the length byte */ | 290 | bt->read_count++; /* account for the length byte */ |
283 | 291 | ||
284 | if (bt_debug & BT_DEBUG_MSG) { | 292 | if (bt_debug & BT_DEBUG_MSG) { |
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
295 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) | 303 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) |
296 | return 1; | 304 | return 1; |
297 | 305 | ||
298 | if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: " | 306 | if (bt_debug & BT_DEBUG_MSG) |
307 | printk(KERN_WARNING "BT: bad packet: " | ||
299 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", | 308 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", |
300 | bt->write_data[1], bt->write_data[2], bt->write_data[3], | 309 | bt->write_data[1], bt->write_data[2], bt->write_data[3], |
301 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); | 310 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); |
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
359 | time); | 368 | time); |
360 | bt->last_state = bt->state; | 369 | bt->last_state = bt->state; |
361 | 370 | ||
362 | if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED; | 371 | if (bt->state == BT_STATE_HOSED) |
372 | return SI_SM_HOSED; | ||
363 | 373 | ||
364 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ | 374 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ |
365 | 375 | ||
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
371 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT | 381 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT |
372 | (noticed in ipmi_smic_sm.c January 2004) */ | 382 | (noticed in ipmi_smic_sm.c January 2004) */ |
373 | 383 | ||
374 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; | 384 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) |
385 | time = 100; | ||
375 | bt->timeout -= time; | 386 | bt->timeout -= time; |
376 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { | 387 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { |
377 | error_recovery(bt, "timed out"); | 388 | error_recovery(bt, "timed out"); |
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
393 | BT_CONTROL(BT_H_BUSY); | 404 | BT_CONTROL(BT_H_BUSY); |
394 | break; | 405 | break; |
395 | } | 406 | } |
396 | if (status & BT_B2H_ATN) break; | 407 | if (status & BT_B2H_ATN) |
408 | break; | ||
397 | bt->state = BT_STATE_WRITE_BYTES; | 409 | bt->state = BT_STATE_WRITE_BYTES; |
398 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 410 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
399 | 411 | ||
400 | case BT_STATE_WRITE_BYTES: | 412 | case BT_STATE_WRITE_BYTES: |
401 | if (status & (BT_B_BUSY | BT_H2B_ATN)) break; | 413 | if (status & (BT_B_BUSY | BT_H2B_ATN)) |
414 | break; | ||
402 | BT_CONTROL(BT_CLR_WR_PTR); | 415 | BT_CONTROL(BT_CLR_WR_PTR); |
403 | write_all_bytes(bt); | 416 | write_all_bytes(bt); |
404 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ | 417 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ |
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
406 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ | 419 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ |
407 | 420 | ||
408 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ | 421 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ |
409 | if (status & (BT_H2B_ATN | BT_B_BUSY)) break; | 422 | if (status & (BT_H2B_ATN | BT_B_BUSY)) |
423 | break; | ||
410 | bt->state = BT_STATE_B2H_WAIT; | 424 | bt->state = BT_STATE_B2H_WAIT; |
411 | /* fall through with status */ | 425 | /* fall through with status */ |
412 | 426 | ||
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
415 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ | 429 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ |
416 | 430 | ||
417 | case BT_STATE_B2H_WAIT: | 431 | case BT_STATE_B2H_WAIT: |
418 | if (!(status & BT_B2H_ATN)) break; | 432 | if (!(status & BT_B2H_ATN)) |
433 | break; | ||
419 | 434 | ||
420 | /* Assume ordered, uncached writes: no need to wait */ | 435 | /* Assume ordered, uncached writes: no need to wait */ |
421 | if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */ | 436 | if (!(status & BT_H_BUSY)) |
437 | BT_CONTROL(BT_H_BUSY); /* set */ | ||
422 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ | 438 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ |
423 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ | 439 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ |
424 | i = read_all_bytes(bt); | 440 | i = read_all_bytes(bt); |
425 | BT_CONTROL(BT_H_BUSY); /* clear */ | 441 | BT_CONTROL(BT_H_BUSY); /* clear */ |
426 | if (!i) break; /* Try this state again */ | 442 | if (!i) /* Try this state again */ |
443 | break; | ||
427 | bt->state = BT_STATE_READ_END; | 444 | bt->state = BT_STATE_READ_END; |
428 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 445 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
429 | 446 | ||
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
436 | 453 | ||
437 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY | 454 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY |
438 | 455 | ||
439 | if (status & BT_H_BUSY) break; | 456 | if (status & BT_H_BUSY) |
457 | break; | ||
440 | #endif | 458 | #endif |
441 | bt->seq++; | 459 | bt->seq++; |
442 | bt->state = BT_STATE_IDLE; | 460 | bt->state = BT_STATE_IDLE; |
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
459 | break; | 477 | break; |
460 | 478 | ||
461 | case BT_STATE_RESET3: | 479 | case BT_STATE_RESET3: |
462 | if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY; | 480 | if (bt->timeout > 0) |
481 | return SI_SM_CALL_WITH_DELAY; | ||
463 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ | 482 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ |
464 | break; | 483 | break; |
465 | 484 | ||
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt) | |||
485 | but that's what you get from reading a bogus address, so we | 504 | but that's what you get from reading a bogus address, so we |
486 | test that first. The calling routine uses negative logic. */ | 505 | test that first. The calling routine uses negative logic. */ |
487 | 506 | ||
488 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; | 507 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) |
508 | return 1; | ||
489 | reset_flags(bt); | 509 | reset_flags(bt); |
490 | return 0; | 510 | return 0; |
491 | } | 511 | } |
@@ -501,7 +521,6 @@ static int bt_size(void) | |||
501 | 521 | ||
502 | struct si_sm_handlers bt_smi_handlers = | 522 | struct si_sm_handlers bt_smi_handlers = |
503 | { | 523 | { |
504 | .version = IPMI_BT_VERSION, | ||
505 | .init_data = bt_init_data, | 524 | .init_data = bt_init_data, |
506 | .start_transaction = bt_start_transaction, | 525 | .start_transaction = bt_start_transaction, |
507 | .get_result = bt_get_result, | 526 | .get_result = bt_get_result, |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index e0a53570fea1..883ac4352be4 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -47,8 +47,6 @@ | |||
47 | #include <linux/device.h> | 47 | #include <linux/device.h> |
48 | #include <linux/compat.h> | 48 | #include <linux/compat.h> |
49 | 49 | ||
50 | #define IPMI_DEVINTF_VERSION "v33" | ||
51 | |||
52 | struct ipmi_file_private | 50 | struct ipmi_file_private |
53 | { | 51 | { |
54 | ipmi_user_t user; | 52 | ipmi_user_t user; |
@@ -411,6 +409,7 @@ static int ipmi_ioctl(struct inode *inode, | |||
411 | break; | 409 | break; |
412 | } | 410 | } |
413 | 411 | ||
412 | /* The next four are legacy, not per-channel. */ | ||
414 | case IPMICTL_SET_MY_ADDRESS_CMD: | 413 | case IPMICTL_SET_MY_ADDRESS_CMD: |
415 | { | 414 | { |
416 | unsigned int val; | 415 | unsigned int val; |
@@ -420,22 +419,25 @@ static int ipmi_ioctl(struct inode *inode, | |||
420 | break; | 419 | break; |
421 | } | 420 | } |
422 | 421 | ||
423 | ipmi_set_my_address(priv->user, val); | 422 | rv = ipmi_set_my_address(priv->user, 0, val); |
424 | rv = 0; | ||
425 | break; | 423 | break; |
426 | } | 424 | } |
427 | 425 | ||
428 | case IPMICTL_GET_MY_ADDRESS_CMD: | 426 | case IPMICTL_GET_MY_ADDRESS_CMD: |
429 | { | 427 | { |
430 | unsigned int val; | 428 | unsigned int val; |
429 | unsigned char rval; | ||
430 | |||
431 | rv = ipmi_get_my_address(priv->user, 0, &rval); | ||
432 | if (rv) | ||
433 | break; | ||
431 | 434 | ||
432 | val = ipmi_get_my_address(priv->user); | 435 | val = rval; |
433 | 436 | ||
434 | if (copy_to_user(arg, &val, sizeof(val))) { | 437 | if (copy_to_user(arg, &val, sizeof(val))) { |
435 | rv = -EFAULT; | 438 | rv = -EFAULT; |
436 | break; | 439 | break; |
437 | } | 440 | } |
438 | rv = 0; | ||
439 | break; | 441 | break; |
440 | } | 442 | } |
441 | 443 | ||
@@ -448,24 +450,94 @@ static int ipmi_ioctl(struct inode *inode, | |||
448 | break; | 450 | break; |
449 | } | 451 | } |
450 | 452 | ||
451 | ipmi_set_my_LUN(priv->user, val); | 453 | rv = ipmi_set_my_LUN(priv->user, 0, val); |
452 | rv = 0; | ||
453 | break; | 454 | break; |
454 | } | 455 | } |
455 | 456 | ||
456 | case IPMICTL_GET_MY_LUN_CMD: | 457 | case IPMICTL_GET_MY_LUN_CMD: |
457 | { | 458 | { |
458 | unsigned int val; | 459 | unsigned int val; |
460 | unsigned char rval; | ||
459 | 461 | ||
460 | val = ipmi_get_my_LUN(priv->user); | 462 | rv = ipmi_get_my_LUN(priv->user, 0, &rval); |
463 | if (rv) | ||
464 | break; | ||
465 | |||
466 | val = rval; | ||
467 | |||
468 | if (copy_to_user(arg, &val, sizeof(val))) { | ||
469 | rv = -EFAULT; | ||
470 | break; | ||
471 | } | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD: | ||
476 | { | ||
477 | struct ipmi_channel_lun_address_set val; | ||
478 | |||
479 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
480 | rv = -EFAULT; | ||
481 | break; | ||
482 | } | ||
483 | |||
484 | return ipmi_set_my_address(priv->user, val.channel, val.value); | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD: | ||
489 | { | ||
490 | struct ipmi_channel_lun_address_set val; | ||
491 | |||
492 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
493 | rv = -EFAULT; | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | rv = ipmi_get_my_address(priv->user, val.channel, &val.value); | ||
498 | if (rv) | ||
499 | break; | ||
500 | |||
501 | if (copy_to_user(arg, &val, sizeof(val))) { | ||
502 | rv = -EFAULT; | ||
503 | break; | ||
504 | } | ||
505 | break; | ||
506 | } | ||
507 | |||
508 | case IPMICTL_SET_MY_CHANNEL_LUN_CMD: | ||
509 | { | ||
510 | struct ipmi_channel_lun_address_set val; | ||
511 | |||
512 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
513 | rv = -EFAULT; | ||
514 | break; | ||
515 | } | ||
516 | |||
517 | rv = ipmi_set_my_LUN(priv->user, val.channel, val.value); | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | case IPMICTL_GET_MY_CHANNEL_LUN_CMD: | ||
522 | { | ||
523 | struct ipmi_channel_lun_address_set val; | ||
524 | |||
525 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
526 | rv = -EFAULT; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value); | ||
531 | if (rv) | ||
532 | break; | ||
461 | 533 | ||
462 | if (copy_to_user(arg, &val, sizeof(val))) { | 534 | if (copy_to_user(arg, &val, sizeof(val))) { |
463 | rv = -EFAULT; | 535 | rv = -EFAULT; |
464 | break; | 536 | break; |
465 | } | 537 | } |
466 | rv = 0; | ||
467 | break; | 538 | break; |
468 | } | 539 | } |
540 | |||
469 | case IPMICTL_SET_TIMING_PARMS_CMD: | 541 | case IPMICTL_SET_TIMING_PARMS_CMD: |
470 | { | 542 | { |
471 | struct ipmi_timing_parms parms; | 543 | struct ipmi_timing_parms parms; |
@@ -748,8 +820,7 @@ static __init int init_ipmi_devintf(void) | |||
748 | if (ipmi_major < 0) | 820 | if (ipmi_major < 0) |
749 | return -EINVAL; | 821 | return -EINVAL; |
750 | 822 | ||
751 | printk(KERN_INFO "ipmi device interface version " | 823 | printk(KERN_INFO "ipmi device interface\n"); |
752 | IPMI_DEVINTF_VERSION "\n"); | ||
753 | 824 | ||
754 | ipmi_class = class_create(THIS_MODULE, "ipmi"); | 825 | ipmi_class = class_create(THIS_MODULE, "ipmi"); |
755 | if (IS_ERR(ipmi_class)) { | 826 | if (IS_ERR(ipmi_class)) { |
@@ -792,3 +863,5 @@ static __exit void cleanup_ipmi(void) | |||
792 | module_exit(cleanup_ipmi); | 863 | module_exit(cleanup_ipmi); |
793 | 864 | ||
794 | MODULE_LICENSE("GPL"); | 865 | MODULE_LICENSE("GPL"); |
866 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
867 | MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); | ||
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index 48cce24329be..d21853a594a3 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c | |||
@@ -42,8 +42,6 @@ | |||
42 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 42 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
43 | #include "ipmi_si_sm.h" | 43 | #include "ipmi_si_sm.h" |
44 | 44 | ||
45 | #define IPMI_KCS_VERSION "v33" | ||
46 | |||
47 | /* Set this if you want a printout of why the state machine was hosed | 45 | /* Set this if you want a printout of why the state machine was hosed |
48 | when it gets hosed. */ | 46 | when it gets hosed. */ |
49 | #define DEBUG_HOSED_REASON | 47 | #define DEBUG_HOSED_REASON |
@@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs) | |||
489 | 487 | ||
490 | struct si_sm_handlers kcs_smi_handlers = | 488 | struct si_sm_handlers kcs_smi_handlers = |
491 | { | 489 | { |
492 | .version = IPMI_KCS_VERSION, | ||
493 | .init_data = init_kcs_data, | 490 | .init_data = init_kcs_data, |
494 | .start_transaction = start_kcs_transaction, | 491 | .start_transaction = start_kcs_transaction, |
495 | .get_result = get_kcs_result, | 492 | .get_result = get_kcs_result, |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e16c13fe698d..463351d4f942 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -47,7 +47,8 @@ | |||
47 | #include <linux/proc_fs.h> | 47 | #include <linux/proc_fs.h> |
48 | 48 | ||
49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
50 | #define IPMI_MSGHANDLER_VERSION "v33" | 50 | |
51 | #define IPMI_DRIVER_VERSION "36.0" | ||
51 | 52 | ||
52 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
53 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
@@ -116,7 +117,7 @@ struct seq_table | |||
116 | do { \ | 117 | do { \ |
117 | seq = ((msgid >> 26) & 0x3f); \ | 118 | seq = ((msgid >> 26) & 0x3f); \ |
118 | seqid = (msgid & 0x3fffff); \ | 119 | seqid = (msgid & 0x3fffff); \ |
119 | } while(0) | 120 | } while (0) |
120 | 121 | ||
121 | #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) | 122 | #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) |
122 | 123 | ||
@@ -124,6 +125,14 @@ struct ipmi_channel | |||
124 | { | 125 | { |
125 | unsigned char medium; | 126 | unsigned char medium; |
126 | unsigned char protocol; | 127 | unsigned char protocol; |
128 | |||
129 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
130 | but may be changed by the user. */ | ||
131 | unsigned char address; | ||
132 | |||
133 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
134 | case... */ | ||
135 | unsigned char lun; | ||
127 | }; | 136 | }; |
128 | 137 | ||
129 | #ifdef CONFIG_PROC_FS | 138 | #ifdef CONFIG_PROC_FS |
@@ -135,7 +144,7 @@ struct ipmi_proc_entry | |||
135 | #endif | 144 | #endif |
136 | 145 | ||
137 | #define IPMI_IPMB_NUM_SEQ 64 | 146 | #define IPMI_IPMB_NUM_SEQ 64 |
138 | #define IPMI_MAX_CHANNELS 8 | 147 | #define IPMI_MAX_CHANNELS 16 |
139 | struct ipmi_smi | 148 | struct ipmi_smi |
140 | { | 149 | { |
141 | /* What interface number are we? */ | 150 | /* What interface number are we? */ |
@@ -193,20 +202,6 @@ struct ipmi_smi | |||
193 | struct list_head waiting_events; | 202 | struct list_head waiting_events; |
194 | unsigned int waiting_events_count; /* How many events in queue? */ | 203 | unsigned int waiting_events_count; /* How many events in queue? */ |
195 | 204 | ||
196 | /* This will be non-null if someone registers to receive all | ||
197 | IPMI commands (this is for interface emulation). There | ||
198 | may not be any things in the cmd_rcvrs list above when | ||
199 | this is registered. */ | ||
200 | ipmi_user_t all_cmd_rcvr; | ||
201 | |||
202 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
203 | but may be changed by the user. */ | ||
204 | unsigned char my_address; | ||
205 | |||
206 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
207 | case... */ | ||
208 | unsigned char my_lun; | ||
209 | |||
210 | /* The event receiver for my BMC, only really used at panic | 205 | /* The event receiver for my BMC, only really used at panic |
211 | shutdown as a place to store this. */ | 206 | shutdown as a place to store this. */ |
212 | unsigned char event_receiver; | 207 | unsigned char event_receiver; |
@@ -218,7 +213,7 @@ struct ipmi_smi | |||
218 | interface comes in with a NULL user, call this routine with | 213 | interface comes in with a NULL user, call this routine with |
219 | it. Note that the message will still be freed by the | 214 | it. Note that the message will still be freed by the |
220 | caller. This only works on the system interface. */ | 215 | caller. This only works on the system interface. */ |
221 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg); | 216 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg); |
222 | 217 | ||
223 | /* When we are scanning the channels for an SMI, this will | 218 | /* When we are scanning the channels for an SMI, this will |
224 | tell which channel we are scanning. */ | 219 | tell which channel we are scanning. */ |
@@ -325,7 +320,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | |||
325 | down_read(&interfaces_sem); | 320 | down_read(&interfaces_sem); |
326 | down_write(&smi_watchers_sem); | 321 | down_write(&smi_watchers_sem); |
327 | list_add(&(watcher->link), &smi_watchers); | 322 | list_add(&(watcher->link), &smi_watchers); |
328 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 323 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
329 | if (ipmi_interfaces[i] != NULL) { | 324 | if (ipmi_interfaces[i] != NULL) { |
330 | watcher->new_smi(i); | 325 | watcher->new_smi(i); |
331 | } | 326 | } |
@@ -458,7 +453,27 @@ unsigned int ipmi_addr_length(int addr_type) | |||
458 | 453 | ||
459 | static void deliver_response(struct ipmi_recv_msg *msg) | 454 | static void deliver_response(struct ipmi_recv_msg *msg) |
460 | { | 455 | { |
461 | msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data); | 456 | if (! msg->user) { |
457 | ipmi_smi_t intf = msg->user_msg_data; | ||
458 | unsigned long flags; | ||
459 | |||
460 | /* Special handling for NULL users. */ | ||
461 | if (intf->null_user_handler) { | ||
462 | intf->null_user_handler(intf, msg); | ||
463 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
464 | intf->handled_local_responses++; | ||
465 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
466 | } else { | ||
467 | /* No handler, so give up. */ | ||
468 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
469 | intf->unhandled_local_responses++; | ||
470 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
471 | } | ||
472 | ipmi_free_recv_msg(msg); | ||
473 | } else { | ||
474 | msg->user->handler->ipmi_recv_hndl(msg, | ||
475 | msg->user->handler_data); | ||
476 | } | ||
462 | } | 477 | } |
463 | 478 | ||
464 | /* Find the next sequence number not being used and add the given | 479 | /* Find the next sequence number not being used and add the given |
@@ -475,9 +490,9 @@ static int intf_next_seq(ipmi_smi_t intf, | |||
475 | int rv = 0; | 490 | int rv = 0; |
476 | unsigned int i; | 491 | unsigned int i; |
477 | 492 | ||
478 | for (i=intf->curr_seq; | 493 | for (i = intf->curr_seq; |
479 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; | 494 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; |
480 | i=(i+1)%IPMI_IPMB_NUM_SEQ) | 495 | i = (i+1)%IPMI_IPMB_NUM_SEQ) |
481 | { | 496 | { |
482 | if (! intf->seq_table[i].inuse) | 497 | if (! intf->seq_table[i].inuse) |
483 | break; | 498 | break; |
@@ -712,7 +727,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user) | |||
712 | 727 | ||
713 | /* Remove the user from the interfaces sequence table. */ | 728 | /* Remove the user from the interfaces sequence table. */ |
714 | spin_lock_irqsave(&(user->intf->seq_lock), flags); | 729 | spin_lock_irqsave(&(user->intf->seq_lock), flags); |
715 | for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) { | 730 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
716 | if (user->intf->seq_table[i].inuse | 731 | if (user->intf->seq_table[i].inuse |
717 | && (user->intf->seq_table[i].recv_msg->user == user)) | 732 | && (user->intf->seq_table[i].recv_msg->user == user)) |
718 | { | 733 | { |
@@ -766,26 +781,44 @@ void ipmi_get_version(ipmi_user_t user, | |||
766 | *minor = user->intf->version_minor; | 781 | *minor = user->intf->version_minor; |
767 | } | 782 | } |
768 | 783 | ||
769 | void ipmi_set_my_address(ipmi_user_t user, | 784 | int ipmi_set_my_address(ipmi_user_t user, |
770 | unsigned char address) | 785 | unsigned int channel, |
786 | unsigned char address) | ||
771 | { | 787 | { |
772 | user->intf->my_address = address; | 788 | if (channel >= IPMI_MAX_CHANNELS) |
789 | return -EINVAL; | ||
790 | user->intf->channels[channel].address = address; | ||
791 | return 0; | ||
773 | } | 792 | } |
774 | 793 | ||
775 | unsigned char ipmi_get_my_address(ipmi_user_t user) | 794 | int ipmi_get_my_address(ipmi_user_t user, |
795 | unsigned int channel, | ||
796 | unsigned char *address) | ||
776 | { | 797 | { |
777 | return user->intf->my_address; | 798 | if (channel >= IPMI_MAX_CHANNELS) |
799 | return -EINVAL; | ||
800 | *address = user->intf->channels[channel].address; | ||
801 | return 0; | ||
778 | } | 802 | } |
779 | 803 | ||
780 | void ipmi_set_my_LUN(ipmi_user_t user, | 804 | int ipmi_set_my_LUN(ipmi_user_t user, |
781 | unsigned char LUN) | 805 | unsigned int channel, |
806 | unsigned char LUN) | ||
782 | { | 807 | { |
783 | user->intf->my_lun = LUN & 0x3; | 808 | if (channel >= IPMI_MAX_CHANNELS) |
809 | return -EINVAL; | ||
810 | user->intf->channels[channel].lun = LUN & 0x3; | ||
811 | return 0; | ||
784 | } | 812 | } |
785 | 813 | ||
786 | unsigned char ipmi_get_my_LUN(ipmi_user_t user) | 814 | int ipmi_get_my_LUN(ipmi_user_t user, |
815 | unsigned int channel, | ||
816 | unsigned char *address) | ||
787 | { | 817 | { |
788 | return user->intf->my_lun; | 818 | if (channel >= IPMI_MAX_CHANNELS) |
819 | return -EINVAL; | ||
820 | *address = user->intf->channels[channel].lun; | ||
821 | return 0; | ||
789 | } | 822 | } |
790 | 823 | ||
791 | int ipmi_set_gets_events(ipmi_user_t user, int val) | 824 | int ipmi_set_gets_events(ipmi_user_t user, int val) |
@@ -828,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
828 | 861 | ||
829 | read_lock(&(user->intf->users_lock)); | 862 | read_lock(&(user->intf->users_lock)); |
830 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); | 863 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); |
831 | if (user->intf->all_cmd_rcvr != NULL) { | ||
832 | rv = -EBUSY; | ||
833 | goto out_unlock; | ||
834 | } | ||
835 | |||
836 | /* Make sure the command/netfn is not already registered. */ | 864 | /* Make sure the command/netfn is not already registered. */ |
837 | list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { | 865 | list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { |
838 | if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { | 866 | if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { |
@@ -847,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
847 | rcvr->user = user; | 875 | rcvr->user = user; |
848 | list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); | 876 | list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); |
849 | } | 877 | } |
850 | out_unlock: | 878 | |
851 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); | 879 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); |
852 | read_unlock(&(user->intf->users_lock)); | 880 | read_unlock(&(user->intf->users_lock)); |
853 | 881 | ||
@@ -1213,7 +1241,7 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1213 | unsigned char ipmb_seq; | 1241 | unsigned char ipmb_seq; |
1214 | long seqid; | 1242 | long seqid; |
1215 | 1243 | ||
1216 | if (addr->channel > IPMI_NUM_CHANNELS) { | 1244 | if (addr->channel >= IPMI_NUM_CHANNELS) { |
1217 | spin_lock_irqsave(&intf->counter_lock, flags); | 1245 | spin_lock_irqsave(&intf->counter_lock, flags); |
1218 | intf->sent_invalid_commands++; | 1246 | intf->sent_invalid_commands++; |
1219 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 1247 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
@@ -1331,7 +1359,7 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1331 | #ifdef DEBUG_MSGING | 1359 | #ifdef DEBUG_MSGING |
1332 | { | 1360 | { |
1333 | int m; | 1361 | int m; |
1334 | for (m=0; m<smi_msg->data_size; m++) | 1362 | for (m = 0; m < smi_msg->data_size; m++) |
1335 | printk(" %2.2x", smi_msg->data[m]); | 1363 | printk(" %2.2x", smi_msg->data[m]); |
1336 | printk("\n"); | 1364 | printk("\n"); |
1337 | } | 1365 | } |
@@ -1346,6 +1374,18 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1346 | return rv; | 1374 | return rv; |
1347 | } | 1375 | } |
1348 | 1376 | ||
1377 | static int check_addr(ipmi_smi_t intf, | ||
1378 | struct ipmi_addr *addr, | ||
1379 | unsigned char *saddr, | ||
1380 | unsigned char *lun) | ||
1381 | { | ||
1382 | if (addr->channel >= IPMI_MAX_CHANNELS) | ||
1383 | return -EINVAL; | ||
1384 | *lun = intf->channels[addr->channel].lun; | ||
1385 | *saddr = intf->channels[addr->channel].address; | ||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1349 | int ipmi_request_settime(ipmi_user_t user, | 1389 | int ipmi_request_settime(ipmi_user_t user, |
1350 | struct ipmi_addr *addr, | 1390 | struct ipmi_addr *addr, |
1351 | long msgid, | 1391 | long msgid, |
@@ -1355,6 +1395,14 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1355 | int retries, | 1395 | int retries, |
1356 | unsigned int retry_time_ms) | 1396 | unsigned int retry_time_ms) |
1357 | { | 1397 | { |
1398 | unsigned char saddr, lun; | ||
1399 | int rv; | ||
1400 | |||
1401 | if (! user) | ||
1402 | return -EINVAL; | ||
1403 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1404 | if (rv) | ||
1405 | return rv; | ||
1358 | return i_ipmi_request(user, | 1406 | return i_ipmi_request(user, |
1359 | user->intf, | 1407 | user->intf, |
1360 | addr, | 1408 | addr, |
@@ -1363,8 +1411,8 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1363 | user_msg_data, | 1411 | user_msg_data, |
1364 | NULL, NULL, | 1412 | NULL, NULL, |
1365 | priority, | 1413 | priority, |
1366 | user->intf->my_address, | 1414 | saddr, |
1367 | user->intf->my_lun, | 1415 | lun, |
1368 | retries, | 1416 | retries, |
1369 | retry_time_ms); | 1417 | retry_time_ms); |
1370 | } | 1418 | } |
@@ -1378,6 +1426,14 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1378 | struct ipmi_recv_msg *supplied_recv, | 1426 | struct ipmi_recv_msg *supplied_recv, |
1379 | int priority) | 1427 | int priority) |
1380 | { | 1428 | { |
1429 | unsigned char saddr, lun; | ||
1430 | int rv; | ||
1431 | |||
1432 | if (! user) | ||
1433 | return -EINVAL; | ||
1434 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1435 | if (rv) | ||
1436 | return rv; | ||
1381 | return i_ipmi_request(user, | 1437 | return i_ipmi_request(user, |
1382 | user->intf, | 1438 | user->intf, |
1383 | addr, | 1439 | addr, |
@@ -1387,8 +1443,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1387 | supplied_smi, | 1443 | supplied_smi, |
1388 | supplied_recv, | 1444 | supplied_recv, |
1389 | priority, | 1445 | priority, |
1390 | user->intf->my_address, | 1446 | saddr, |
1391 | user->intf->my_lun, | 1447 | lun, |
1392 | -1, 0); | 1448 | -1, 0); |
1393 | } | 1449 | } |
1394 | 1450 | ||
@@ -1397,8 +1453,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, | |||
1397 | { | 1453 | { |
1398 | char *out = (char *) page; | 1454 | char *out = (char *) page; |
1399 | ipmi_smi_t intf = data; | 1455 | ipmi_smi_t intf = data; |
1456 | int i; | ||
1457 | int rv= 0; | ||
1400 | 1458 | ||
1401 | return sprintf(out, "%x\n", intf->my_address); | 1459 | for (i = 0; i < IPMI_MAX_CHANNELS; i++) |
1460 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); | ||
1461 | out[rv-1] = '\n'; /* Replace the final space with a newline */ | ||
1462 | out[rv] = '\0'; | ||
1463 | rv++; | ||
1464 | return rv; | ||
1402 | } | 1465 | } |
1403 | 1466 | ||
1404 | static int version_file_read_proc(char *page, char **start, off_t off, | 1467 | static int version_file_read_proc(char *page, char **start, off_t off, |
@@ -1588,29 +1651,30 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) | |||
1588 | (struct ipmi_addr *) &si, | 1651 | (struct ipmi_addr *) &si, |
1589 | 0, | 1652 | 0, |
1590 | &msg, | 1653 | &msg, |
1591 | NULL, | 1654 | intf, |
1592 | NULL, | 1655 | NULL, |
1593 | NULL, | 1656 | NULL, |
1594 | 0, | 1657 | 0, |
1595 | intf->my_address, | 1658 | intf->channels[0].address, |
1596 | intf->my_lun, | 1659 | intf->channels[0].lun, |
1597 | -1, 0); | 1660 | -1, 0); |
1598 | } | 1661 | } |
1599 | 1662 | ||
1600 | static void | 1663 | static void |
1601 | channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 1664 | channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
1602 | { | 1665 | { |
1603 | int rv = 0; | 1666 | int rv = 0; |
1604 | int chan; | 1667 | int chan; |
1605 | 1668 | ||
1606 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 1669 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
1607 | && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD)) | 1670 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
1671 | && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) | ||
1608 | { | 1672 | { |
1609 | /* It's the one we want */ | 1673 | /* It's the one we want */ |
1610 | if (msg->rsp[2] != 0) { | 1674 | if (msg->msg.data[0] != 0) { |
1611 | /* Got an error from the channel, just go on. */ | 1675 | /* Got an error from the channel, just go on. */ |
1612 | 1676 | ||
1613 | if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { | 1677 | if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { |
1614 | /* If the MC does not support this | 1678 | /* If the MC does not support this |
1615 | command, that is legal. We just | 1679 | command, that is legal. We just |
1616 | assume it has one IPMB at channel | 1680 | assume it has one IPMB at channel |
@@ -1627,13 +1691,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | |||
1627 | } | 1691 | } |
1628 | goto next_channel; | 1692 | goto next_channel; |
1629 | } | 1693 | } |
1630 | if (msg->rsp_size < 6) { | 1694 | if (msg->msg.data_len < 4) { |
1631 | /* Message not big enough, just go on. */ | 1695 | /* Message not big enough, just go on. */ |
1632 | goto next_channel; | 1696 | goto next_channel; |
1633 | } | 1697 | } |
1634 | chan = intf->curr_channel; | 1698 | chan = intf->curr_channel; |
1635 | intf->channels[chan].medium = msg->rsp[4] & 0x7f; | 1699 | intf->channels[chan].medium = msg->msg.data[2] & 0x7f; |
1636 | intf->channels[chan].protocol = msg->rsp[5] & 0x1f; | 1700 | intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; |
1637 | 1701 | ||
1638 | next_channel: | 1702 | next_channel: |
1639 | intf->curr_channel++; | 1703 | intf->curr_channel++; |
@@ -1691,22 +1755,24 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1691 | rv = -ENOMEM; | 1755 | rv = -ENOMEM; |
1692 | 1756 | ||
1693 | down_write(&interfaces_sem); | 1757 | down_write(&interfaces_sem); |
1694 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 1758 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
1695 | if (ipmi_interfaces[i] == NULL) { | 1759 | if (ipmi_interfaces[i] == NULL) { |
1696 | new_intf->intf_num = i; | 1760 | new_intf->intf_num = i; |
1697 | new_intf->version_major = version_major; | 1761 | new_intf->version_major = version_major; |
1698 | new_intf->version_minor = version_minor; | 1762 | new_intf->version_minor = version_minor; |
1699 | if (slave_addr == 0) | 1763 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { |
1700 | new_intf->my_address = IPMI_BMC_SLAVE_ADDR; | 1764 | new_intf->channels[j].address |
1701 | else | 1765 | = IPMI_BMC_SLAVE_ADDR; |
1702 | new_intf->my_address = slave_addr; | 1766 | new_intf->channels[j].lun = 2; |
1703 | new_intf->my_lun = 2; /* the SMS LUN. */ | 1767 | } |
1768 | if (slave_addr != 0) | ||
1769 | new_intf->channels[0].address = slave_addr; | ||
1704 | rwlock_init(&(new_intf->users_lock)); | 1770 | rwlock_init(&(new_intf->users_lock)); |
1705 | INIT_LIST_HEAD(&(new_intf->users)); | 1771 | INIT_LIST_HEAD(&(new_intf->users)); |
1706 | new_intf->handlers = handlers; | 1772 | new_intf->handlers = handlers; |
1707 | new_intf->send_info = send_info; | 1773 | new_intf->send_info = send_info; |
1708 | spin_lock_init(&(new_intf->seq_lock)); | 1774 | spin_lock_init(&(new_intf->seq_lock)); |
1709 | for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) { | 1775 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { |
1710 | new_intf->seq_table[j].inuse = 0; | 1776 | new_intf->seq_table[j].inuse = 0; |
1711 | new_intf->seq_table[j].seqid = 0; | 1777 | new_intf->seq_table[j].seqid = 0; |
1712 | } | 1778 | } |
@@ -1722,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1722 | rwlock_init(&(new_intf->cmd_rcvr_lock)); | 1788 | rwlock_init(&(new_intf->cmd_rcvr_lock)); |
1723 | init_waitqueue_head(&new_intf->waitq); | 1789 | init_waitqueue_head(&new_intf->waitq); |
1724 | INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); | 1790 | INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); |
1725 | new_intf->all_cmd_rcvr = NULL; | ||
1726 | 1791 | ||
1727 | spin_lock_init(&(new_intf->counter_lock)); | 1792 | spin_lock_init(&(new_intf->counter_lock)); |
1728 | 1793 | ||
@@ -1814,7 +1879,7 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
1814 | free_recv_msg_list(&(intf->waiting_events)); | 1879 | free_recv_msg_list(&(intf->waiting_events)); |
1815 | free_cmd_rcvr_list(&(intf->cmd_rcvrs)); | 1880 | free_cmd_rcvr_list(&(intf->cmd_rcvrs)); |
1816 | 1881 | ||
1817 | for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) { | 1882 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
1818 | if ((intf->seq_table[i].inuse) | 1883 | if ((intf->seq_table[i].inuse) |
1819 | && (intf->seq_table[i].recv_msg)) | 1884 | && (intf->seq_table[i].recv_msg)) |
1820 | { | 1885 | { |
@@ -1833,7 +1898,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf) | |||
1833 | down_write(&interfaces_sem); | 1898 | down_write(&interfaces_sem); |
1834 | if (list_empty(&(intf->users))) | 1899 | if (list_empty(&(intf->users))) |
1835 | { | 1900 | { |
1836 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 1901 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
1837 | if (ipmi_interfaces[i] == intf) { | 1902 | if (ipmi_interfaces[i] == intf) { |
1838 | remove_proc_entries(intf); | 1903 | remove_proc_entries(intf); |
1839 | spin_lock_irqsave(&interfaces_lock, flags); | 1904 | spin_lock_irqsave(&interfaces_lock, flags); |
@@ -1960,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1960 | 2025 | ||
1961 | read_lock(&(intf->cmd_rcvr_lock)); | 2026 | read_lock(&(intf->cmd_rcvr_lock)); |
1962 | 2027 | ||
1963 | if (intf->all_cmd_rcvr) { | 2028 | /* Find the command/netfn. */ |
1964 | user = intf->all_cmd_rcvr; | 2029 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { |
1965 | } else { | 2030 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { |
1966 | /* Find the command/netfn. */ | 2031 | user = rcvr->user; |
1967 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2032 | break; |
1968 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | ||
1969 | user = rcvr->user; | ||
1970 | break; | ||
1971 | } | ||
1972 | } | 2033 | } |
1973 | } | 2034 | } |
1974 | read_unlock(&(intf->cmd_rcvr_lock)); | 2035 | read_unlock(&(intf->cmd_rcvr_lock)); |
@@ -1985,7 +2046,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1985 | msg->data[3] = msg->rsp[6]; | 2046 | msg->data[3] = msg->rsp[6]; |
1986 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); | 2047 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); |
1987 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); | 2048 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); |
1988 | msg->data[6] = intf->my_address; | 2049 | msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address; |
1989 | /* rqseq/lun */ | 2050 | /* rqseq/lun */ |
1990 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); | 2051 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); |
1991 | msg->data[8] = msg->rsp[8]; /* cmd */ | 2052 | msg->data[8] = msg->rsp[8]; /* cmd */ |
@@ -1997,7 +2058,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1997 | { | 2058 | { |
1998 | int m; | 2059 | int m; |
1999 | printk("Invalid command:"); | 2060 | printk("Invalid command:"); |
2000 | for (m=0; m<msg->data_size; m++) | 2061 | for (m = 0; m < msg->data_size; m++) |
2001 | printk(" %2.2x", msg->data[m]); | 2062 | printk(" %2.2x", msg->data[m]); |
2002 | printk("\n"); | 2063 | printk("\n"); |
2003 | } | 2064 | } |
@@ -2145,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
2145 | 2206 | ||
2146 | read_lock(&(intf->cmd_rcvr_lock)); | 2207 | read_lock(&(intf->cmd_rcvr_lock)); |
2147 | 2208 | ||
2148 | if (intf->all_cmd_rcvr) { | 2209 | /* Find the command/netfn. */ |
2149 | user = intf->all_cmd_rcvr; | 2210 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { |
2150 | } else { | 2211 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { |
2151 | /* Find the command/netfn. */ | 2212 | user = rcvr->user; |
2152 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2213 | break; |
2153 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | ||
2154 | user = rcvr->user; | ||
2155 | break; | ||
2156 | } | ||
2157 | } | 2214 | } |
2158 | } | 2215 | } |
2159 | read_unlock(&(intf->cmd_rcvr_lock)); | 2216 | read_unlock(&(intf->cmd_rcvr_lock)); |
@@ -2330,6 +2387,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2330 | unsigned long flags; | 2387 | unsigned long flags; |
2331 | 2388 | ||
2332 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; | 2389 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
2390 | if (recv_msg == NULL) | ||
2391 | { | ||
2392 | printk(KERN_WARNING"IPMI message received with no owner. This\n" | ||
2393 | "could be because of a malformed message, or\n" | ||
2394 | "because of a hardware error. Contact your\n" | ||
2395 | "hardware vender for assistance\n"); | ||
2396 | return 0; | ||
2397 | } | ||
2333 | 2398 | ||
2334 | /* Make sure the user still exists. */ | 2399 | /* Make sure the user still exists. */ |
2335 | list_for_each_entry(user, &(intf->users), link) { | 2400 | list_for_each_entry(user, &(intf->users), link) { |
@@ -2340,19 +2405,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2340 | } | 2405 | } |
2341 | } | 2406 | } |
2342 | 2407 | ||
2343 | if (!found) { | 2408 | if ((! found) && recv_msg->user) { |
2344 | /* Special handling for NULL users. */ | 2409 | /* The user for the message went away, so give up. */ |
2345 | if (!recv_msg->user && intf->null_user_handler){ | 2410 | spin_lock_irqsave(&intf->counter_lock, flags); |
2346 | intf->null_user_handler(intf, msg); | 2411 | intf->unhandled_local_responses++; |
2347 | spin_lock_irqsave(&intf->counter_lock, flags); | 2412 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
2348 | intf->handled_local_responses++; | ||
2349 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2350 | }else{ | ||
2351 | /* The user for the message went away, so give up. */ | ||
2352 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
2353 | intf->unhandled_local_responses++; | ||
2354 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2355 | } | ||
2356 | ipmi_free_recv_msg(recv_msg); | 2413 | ipmi_free_recv_msg(recv_msg); |
2357 | } else { | 2414 | } else { |
2358 | struct ipmi_system_interface_addr *smi_addr; | 2415 | struct ipmi_system_interface_addr *smi_addr; |
@@ -2392,7 +2449,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
2392 | #ifdef DEBUG_MSGING | 2449 | #ifdef DEBUG_MSGING |
2393 | int m; | 2450 | int m; |
2394 | printk("Recv:"); | 2451 | printk("Recv:"); |
2395 | for (m=0; m<msg->rsp_size; m++) | 2452 | for (m = 0; m < msg->rsp_size; m++) |
2396 | printk(" %2.2x", msg->rsp[m]); | 2453 | printk(" %2.2x", msg->rsp[m]); |
2397 | printk("\n"); | 2454 | printk("\n"); |
2398 | #endif | 2455 | #endif |
@@ -2626,7 +2683,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, | |||
2626 | { | 2683 | { |
2627 | int m; | 2684 | int m; |
2628 | printk("Resend: "); | 2685 | printk("Resend: "); |
2629 | for (m=0; m<smi_msg->data_size; m++) | 2686 | for (m = 0; m < smi_msg->data_size; m++) |
2630 | printk(" %2.2x", smi_msg->data[m]); | 2687 | printk(" %2.2x", smi_msg->data[m]); |
2631 | printk("\n"); | 2688 | printk("\n"); |
2632 | } | 2689 | } |
@@ -2647,7 +2704,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2647 | INIT_LIST_HEAD(&timeouts); | 2704 | INIT_LIST_HEAD(&timeouts); |
2648 | 2705 | ||
2649 | spin_lock(&interfaces_lock); | 2706 | spin_lock(&interfaces_lock); |
2650 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2707 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2651 | intf = ipmi_interfaces[i]; | 2708 | intf = ipmi_interfaces[i]; |
2652 | if (intf == NULL) | 2709 | if (intf == NULL) |
2653 | continue; | 2710 | continue; |
@@ -2672,7 +2729,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2672 | have timed out, putting them in the timeouts | 2729 | have timed out, putting them in the timeouts |
2673 | list. */ | 2730 | list. */ |
2674 | spin_lock_irqsave(&(intf->seq_lock), flags); | 2731 | spin_lock_irqsave(&(intf->seq_lock), flags); |
2675 | for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) { | 2732 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { |
2676 | struct seq_table *ent = &(intf->seq_table[j]); | 2733 | struct seq_table *ent = &(intf->seq_table[j]); |
2677 | if (!ent->inuse) | 2734 | if (!ent->inuse) |
2678 | continue; | 2735 | continue; |
@@ -2712,7 +2769,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2712 | spin_unlock(&intf->counter_lock); | 2769 | spin_unlock(&intf->counter_lock); |
2713 | smi_msg = smi_from_recv_msg(intf, | 2770 | smi_msg = smi_from_recv_msg(intf, |
2714 | ent->recv_msg, j, ent->seqid); | 2771 | ent->recv_msg, j, ent->seqid); |
2715 | if(!smi_msg) | 2772 | if (! smi_msg) |
2716 | continue; | 2773 | continue; |
2717 | 2774 | ||
2718 | spin_unlock_irqrestore(&(intf->seq_lock),flags); | 2775 | spin_unlock_irqrestore(&(intf->seq_lock),flags); |
@@ -2743,7 +2800,7 @@ static void ipmi_request_event(void) | |||
2743 | int i; | 2800 | int i; |
2744 | 2801 | ||
2745 | spin_lock(&interfaces_lock); | 2802 | spin_lock(&interfaces_lock); |
2746 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2803 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2747 | intf = ipmi_interfaces[i]; | 2804 | intf = ipmi_interfaces[i]; |
2748 | if (intf == NULL) | 2805 | if (intf == NULL) |
2749 | continue; | 2806 | continue; |
@@ -2838,28 +2895,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) | |||
2838 | } | 2895 | } |
2839 | 2896 | ||
2840 | #ifdef CONFIG_IPMI_PANIC_STRING | 2897 | #ifdef CONFIG_IPMI_PANIC_STRING |
2841 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2898 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2842 | { | 2899 | { |
2843 | if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2)) | 2900 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2844 | && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD) | 2901 | && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE) |
2845 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2902 | && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD) |
2903 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2846 | { | 2904 | { |
2847 | /* A get event receiver command, save it. */ | 2905 | /* A get event receiver command, save it. */ |
2848 | intf->event_receiver = msg->rsp[3]; | 2906 | intf->event_receiver = msg->msg.data[1]; |
2849 | intf->event_receiver_lun = msg->rsp[4] & 0x3; | 2907 | intf->event_receiver_lun = msg->msg.data[2] & 0x3; |
2850 | } | 2908 | } |
2851 | } | 2909 | } |
2852 | 2910 | ||
2853 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2911 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2854 | { | 2912 | { |
2855 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 2913 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2856 | && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD) | 2914 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
2857 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2915 | && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD) |
2916 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2858 | { | 2917 | { |
2859 | /* A get device id command, save if we are an event | 2918 | /* A get device id command, save if we are an event |
2860 | receiver or generator. */ | 2919 | receiver or generator. */ |
2861 | intf->local_sel_device = (msg->rsp[8] >> 2) & 1; | 2920 | intf->local_sel_device = (msg->msg.data[6] >> 2) & 1; |
2862 | intf->local_event_generator = (msg->rsp[8] >> 5) & 1; | 2921 | intf->local_event_generator = (msg->msg.data[6] >> 5) & 1; |
2863 | } | 2922 | } |
2864 | } | 2923 | } |
2865 | #endif | 2924 | #endif |
@@ -2903,7 +2962,7 @@ static void send_panic_events(char *str) | |||
2903 | recv_msg.done = dummy_recv_done_handler; | 2962 | recv_msg.done = dummy_recv_done_handler; |
2904 | 2963 | ||
2905 | /* For every registered interface, send the event. */ | 2964 | /* For every registered interface, send the event. */ |
2906 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2965 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2907 | intf = ipmi_interfaces[i]; | 2966 | intf = ipmi_interfaces[i]; |
2908 | if (intf == NULL) | 2967 | if (intf == NULL) |
2909 | continue; | 2968 | continue; |
@@ -2915,12 +2974,12 @@ static void send_panic_events(char *str) | |||
2915 | &addr, | 2974 | &addr, |
2916 | 0, | 2975 | 0, |
2917 | &msg, | 2976 | &msg, |
2918 | NULL, | 2977 | intf, |
2919 | &smi_msg, | 2978 | &smi_msg, |
2920 | &recv_msg, | 2979 | &recv_msg, |
2921 | 0, | 2980 | 0, |
2922 | intf->my_address, | 2981 | intf->channels[0].address, |
2923 | intf->my_lun, | 2982 | intf->channels[0].lun, |
2924 | 0, 1); /* Don't retry, and don't wait. */ | 2983 | 0, 1); /* Don't retry, and don't wait. */ |
2925 | } | 2984 | } |
2926 | 2985 | ||
@@ -2930,7 +2989,7 @@ static void send_panic_events(char *str) | |||
2930 | if (!str) | 2989 | if (!str) |
2931 | return; | 2990 | return; |
2932 | 2991 | ||
2933 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2992 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2934 | char *p = str; | 2993 | char *p = str; |
2935 | struct ipmi_ipmb_addr *ipmb; | 2994 | struct ipmi_ipmb_addr *ipmb; |
2936 | int j; | 2995 | int j; |
@@ -2961,12 +3020,12 @@ static void send_panic_events(char *str) | |||
2961 | &addr, | 3020 | &addr, |
2962 | 0, | 3021 | 0, |
2963 | &msg, | 3022 | &msg, |
2964 | NULL, | 3023 | intf, |
2965 | &smi_msg, | 3024 | &smi_msg, |
2966 | &recv_msg, | 3025 | &recv_msg, |
2967 | 0, | 3026 | 0, |
2968 | intf->my_address, | 3027 | intf->channels[0].address, |
2969 | intf->my_lun, | 3028 | intf->channels[0].lun, |
2970 | 0, 1); /* Don't retry, and don't wait. */ | 3029 | 0, 1); /* Don't retry, and don't wait. */ |
2971 | 3030 | ||
2972 | if (intf->local_event_generator) { | 3031 | if (intf->local_event_generator) { |
@@ -2981,12 +3040,12 @@ static void send_panic_events(char *str) | |||
2981 | &addr, | 3040 | &addr, |
2982 | 0, | 3041 | 0, |
2983 | &msg, | 3042 | &msg, |
2984 | NULL, | 3043 | intf, |
2985 | &smi_msg, | 3044 | &smi_msg, |
2986 | &recv_msg, | 3045 | &recv_msg, |
2987 | 0, | 3046 | 0, |
2988 | intf->my_address, | 3047 | intf->channels[0].address, |
2989 | intf->my_lun, | 3048 | intf->channels[0].lun, |
2990 | 0, 1); /* no retry, and no wait. */ | 3049 | 0, 1); /* no retry, and no wait. */ |
2991 | } | 3050 | } |
2992 | intf->null_user_handler = NULL; | 3051 | intf->null_user_handler = NULL; |
@@ -2996,7 +3055,7 @@ static void send_panic_events(char *str) | |||
2996 | be zero, and it must not be my address. */ | 3055 | be zero, and it must not be my address. */ |
2997 | if (((intf->event_receiver & 1) == 0) | 3056 | if (((intf->event_receiver & 1) == 0) |
2998 | && (intf->event_receiver != 0) | 3057 | && (intf->event_receiver != 0) |
2999 | && (intf->event_receiver != intf->my_address)) | 3058 | && (intf->event_receiver != intf->channels[0].address)) |
3000 | { | 3059 | { |
3001 | /* The event receiver is valid, send an IPMB | 3060 | /* The event receiver is valid, send an IPMB |
3002 | message. */ | 3061 | message. */ |
@@ -3031,7 +3090,7 @@ static void send_panic_events(char *str) | |||
3031 | data[0] = 0; | 3090 | data[0] = 0; |
3032 | data[1] = 0; | 3091 | data[1] = 0; |
3033 | data[2] = 0xf0; /* OEM event without timestamp. */ | 3092 | data[2] = 0xf0; /* OEM event without timestamp. */ |
3034 | data[3] = intf->my_address; | 3093 | data[3] = intf->channels[0].address; |
3035 | data[4] = j++; /* sequence # */ | 3094 | data[4] = j++; /* sequence # */ |
3036 | /* Always give 11 bytes, so strncpy will fill | 3095 | /* Always give 11 bytes, so strncpy will fill |
3037 | it with zeroes for me. */ | 3096 | it with zeroes for me. */ |
@@ -3043,12 +3102,12 @@ static void send_panic_events(char *str) | |||
3043 | &addr, | 3102 | &addr, |
3044 | 0, | 3103 | 0, |
3045 | &msg, | 3104 | &msg, |
3046 | NULL, | 3105 | intf, |
3047 | &smi_msg, | 3106 | &smi_msg, |
3048 | &recv_msg, | 3107 | &recv_msg, |
3049 | 0, | 3108 | 0, |
3050 | intf->my_address, | 3109 | intf->channels[0].address, |
3051 | intf->my_lun, | 3110 | intf->channels[0].lun, |
3052 | 0, 1); /* no retry, and no wait. */ | 3111 | 0, 1); /* no retry, and no wait. */ |
3053 | } | 3112 | } |
3054 | } | 3113 | } |
@@ -3070,7 +3129,7 @@ static int panic_event(struct notifier_block *this, | |||
3070 | has_paniced = 1; | 3129 | has_paniced = 1; |
3071 | 3130 | ||
3072 | /* For every registered interface, set it to run to completion. */ | 3131 | /* For every registered interface, set it to run to completion. */ |
3073 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 3132 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
3074 | intf = ipmi_interfaces[i]; | 3133 | intf = ipmi_interfaces[i]; |
3075 | if (intf == NULL) | 3134 | if (intf == NULL) |
3076 | continue; | 3135 | continue; |
@@ -3099,9 +3158,9 @@ static int ipmi_init_msghandler(void) | |||
3099 | return 0; | 3158 | return 0; |
3100 | 3159 | ||
3101 | printk(KERN_INFO "ipmi message handler version " | 3160 | printk(KERN_INFO "ipmi message handler version " |
3102 | IPMI_MSGHANDLER_VERSION "\n"); | 3161 | IPMI_DRIVER_VERSION "\n"); |
3103 | 3162 | ||
3104 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 3163 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
3105 | ipmi_interfaces[i] = NULL; | 3164 | ipmi_interfaces[i] = NULL; |
3106 | } | 3165 | } |
3107 | 3166 | ||
@@ -3171,6 +3230,9 @@ module_exit(cleanup_ipmi); | |||
3171 | 3230 | ||
3172 | module_init(ipmi_init_msghandler_mod); | 3231 | module_init(ipmi_init_msghandler_mod); |
3173 | MODULE_LICENSE("GPL"); | 3232 | MODULE_LICENSE("GPL"); |
3233 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
3234 | MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface."); | ||
3235 | MODULE_VERSION(IPMI_DRIVER_VERSION); | ||
3174 | 3236 | ||
3175 | EXPORT_SYMBOL(ipmi_create_user); | 3237 | EXPORT_SYMBOL(ipmi_create_user); |
3176 | EXPORT_SYMBOL(ipmi_destroy_user); | 3238 | EXPORT_SYMBOL(ipmi_destroy_user); |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index f951c30236c9..e82a96ba396b 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/ipmi_smi.h> | 42 | #include <linux/ipmi_smi.h> |
43 | 43 | ||
44 | #define PFX "IPMI poweroff: " | 44 | #define PFX "IPMI poweroff: " |
45 | #define IPMI_POWEROFF_VERSION "v33" | ||
46 | 45 | ||
47 | /* Where to we insert our poweroff function? */ | 46 | /* Where to we insert our poweroff function? */ |
48 | extern void (*pm_power_off)(void); | 47 | extern void (*pm_power_off)(void); |
@@ -53,16 +52,17 @@ extern void (*pm_power_off)(void); | |||
53 | #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ | 52 | #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ |
54 | 53 | ||
55 | /* the IPMI data command */ | 54 | /* the IPMI data command */ |
56 | static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 55 | static int poweroff_powercycle; |
57 | 56 | ||
58 | /* parameter definition to allow user to flag power cycle */ | 57 | /* parameter definition to allow user to flag power cycle */ |
59 | module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); | 58 | module_param(poweroff_powercycle, int, 0); |
60 | MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); | 59 | MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); |
61 | 60 | ||
62 | /* Stuff from the get device id command. */ | 61 | /* Stuff from the get device id command. */ |
63 | static unsigned int mfg_id; | 62 | static unsigned int mfg_id; |
64 | static unsigned int prod_id; | 63 | static unsigned int prod_id; |
65 | static unsigned char capabilities; | 64 | static unsigned char capabilities; |
65 | static unsigned char ipmi_version; | ||
66 | 66 | ||
67 | /* We use our own messages for this operation, we don't let the system | 67 | /* We use our own messages for this operation, we don't let the system |
68 | allocate them, since we may be in a panic situation. The whole | 68 | allocate them, since we may be in a panic situation. The whole |
@@ -338,6 +338,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user) | |||
338 | } | 338 | } |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * ipmi_dell_chassis_detect() | ||
342 | * Dell systems with IPMI < 1.5 don't set the chassis capability bit | ||
343 | * but they can handle a chassis poweroff or powercycle command. | ||
344 | */ | ||
345 | |||
346 | #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} | ||
347 | static int ipmi_dell_chassis_detect (ipmi_user_t user) | ||
348 | { | ||
349 | const char ipmi_version_major = ipmi_version & 0xF; | ||
350 | const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; | ||
351 | const char mfr[3]=DELL_IANA_MFR_ID; | ||
352 | if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && | ||
353 | ipmi_version_major <= 1 && | ||
354 | ipmi_version_minor < 5) | ||
355 | return 1; | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | /* | ||
341 | * Standard chassis support | 360 | * Standard chassis support |
342 | */ | 361 | */ |
343 | 362 | ||
@@ -366,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user) | |||
366 | 385 | ||
367 | powercyclefailed: | 386 | powercyclefailed: |
368 | printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", | 387 | printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", |
369 | ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); | 388 | (poweroff_powercycle ? "cycle" : "down")); |
370 | 389 | ||
371 | /* | 390 | /* |
372 | * Power down | 391 | * Power down |
373 | */ | 392 | */ |
374 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; | 393 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; |
375 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; | 394 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; |
376 | data[0] = poweroff_control; | 395 | if (poweroff_powercycle) |
396 | data[0] = IPMI_CHASSIS_POWER_CYCLE; | ||
397 | else | ||
398 | data[0] = IPMI_CHASSIS_POWER_DOWN; | ||
377 | send_msg.data = data; | 399 | send_msg.data = data; |
378 | send_msg.data_len = sizeof(data); | 400 | send_msg.data_len = sizeof(data); |
379 | rv = ipmi_request_in_rc_mode(user, | 401 | rv = ipmi_request_in_rc_mode(user, |
380 | (struct ipmi_addr *) &smi_addr, | 402 | (struct ipmi_addr *) &smi_addr, |
381 | &send_msg); | 403 | &send_msg); |
382 | if (rv) { | 404 | if (rv) { |
383 | switch (poweroff_control) { | 405 | if (poweroff_powercycle) { |
384 | case IPMI_CHASSIS_POWER_CYCLE: | 406 | /* power cycle failed, default to power down */ |
385 | /* power cycle failed, default to power down */ | 407 | printk(KERN_ERR PFX "Unable to send chassis power " \ |
386 | printk(KERN_ERR PFX "Unable to send chassis power " \ | 408 | "cycle message, IPMI error 0x%x\n", rv); |
387 | "cycle message, IPMI error 0x%x\n", rv); | 409 | poweroff_powercycle = 0; |
388 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 410 | goto powercyclefailed; |
389 | goto powercyclefailed; | ||
390 | |||
391 | case IPMI_CHASSIS_POWER_DOWN: | ||
392 | default: | ||
393 | printk(KERN_ERR PFX "Unable to send chassis power " \ | ||
394 | "down message, IPMI error 0x%x\n", rv); | ||
395 | break; | ||
396 | } | 411 | } |
397 | } | ||
398 | 412 | ||
399 | return; | 413 | printk(KERN_ERR PFX "Unable to send chassis power " \ |
414 | "down message, IPMI error 0x%x\n", rv); | ||
415 | } | ||
400 | } | 416 | } |
401 | 417 | ||
402 | 418 | ||
@@ -414,6 +430,9 @@ static struct poweroff_function poweroff_functions[] = { | |||
414 | { .platform_type = "CPI1", | 430 | { .platform_type = "CPI1", |
415 | .detect = ipmi_cpi1_detect, | 431 | .detect = ipmi_cpi1_detect, |
416 | .poweroff_func = ipmi_poweroff_cpi1 }, | 432 | .poweroff_func = ipmi_poweroff_cpi1 }, |
433 | { .platform_type = "chassis", | ||
434 | .detect = ipmi_dell_chassis_detect, | ||
435 | .poweroff_func = ipmi_poweroff_chassis }, | ||
417 | /* Chassis should generally be last, other things should override | 436 | /* Chassis should generally be last, other things should override |
418 | it. */ | 437 | it. */ |
419 | { .platform_type = "chassis", | 438 | { .platform_type = "chassis", |
@@ -499,10 +518,11 @@ static void ipmi_po_new_smi(int if_num) | |||
499 | prod_id = (halt_recv_msg.msg.data[10] | 518 | prod_id = (halt_recv_msg.msg.data[10] |
500 | | (halt_recv_msg.msg.data[11] << 8)); | 519 | | (halt_recv_msg.msg.data[11] << 8)); |
501 | capabilities = halt_recv_msg.msg.data[6]; | 520 | capabilities = halt_recv_msg.msg.data[6]; |
521 | ipmi_version = halt_recv_msg.msg.data[5]; | ||
502 | 522 | ||
503 | 523 | ||
504 | /* Scan for a poweroff method */ | 524 | /* Scan for a poweroff method */ |
505 | for (i=0; i<NUM_PO_FUNCS; i++) { | 525 | for (i = 0; i < NUM_PO_FUNCS; i++) { |
506 | if (poweroff_functions[i].detect(ipmi_user)) | 526 | if (poweroff_functions[i].detect(ipmi_user)) |
507 | goto found; | 527 | goto found; |
508 | } | 528 | } |
@@ -538,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher = | |||
538 | 558 | ||
539 | 559 | ||
540 | #ifdef CONFIG_PROC_FS | 560 | #ifdef CONFIG_PROC_FS |
541 | /* displays properties to proc */ | 561 | #include <linux/sysctl.h> |
542 | static int proc_read_chassctrl(char *page, char **start, off_t off, int count, | 562 | |
543 | int *eof, void *data) | 563 | static ctl_table ipmi_table[] = { |
544 | { | 564 | { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE, |
545 | return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", | 565 | .procname = "poweroff_powercycle", |
546 | poweroff_control); | 566 | .data = &poweroff_powercycle, |
547 | } | 567 | .maxlen = sizeof(poweroff_powercycle), |
568 | .mode = 0644, | ||
569 | .proc_handler = &proc_dointvec }, | ||
570 | { } | ||
571 | }; | ||
548 | 572 | ||
549 | /* process property writes from proc */ | 573 | static ctl_table ipmi_dir_table[] = { |
550 | static int proc_write_chassctrl(struct file *file, const char *buffer, | 574 | { .ctl_name = DEV_IPMI, |
551 | unsigned long count, void *data) | 575 | .procname = "ipmi", |
552 | { | 576 | .mode = 0555, |
553 | int rv = count; | 577 | .child = ipmi_table }, |
554 | unsigned int newval = 0; | 578 | { } |
555 | 579 | }; | |
556 | sscanf(buffer, "%d", &newval); | ||
557 | switch (newval) { | ||
558 | case IPMI_CHASSIS_POWER_CYCLE: | ||
559 | printk(KERN_INFO PFX "power cycle is now enabled\n"); | ||
560 | poweroff_control = newval; | ||
561 | break; | ||
562 | |||
563 | case IPMI_CHASSIS_POWER_DOWN: | ||
564 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
565 | break; | ||
566 | |||
567 | default: | ||
568 | rv = -EINVAL; | ||
569 | break; | ||
570 | } | ||
571 | 580 | ||
572 | return rv; | 581 | static ctl_table ipmi_root_table[] = { |
573 | } | 582 | { .ctl_name = CTL_DEV, |
583 | .procname = "dev", | ||
584 | .mode = 0555, | ||
585 | .child = ipmi_dir_table }, | ||
586 | { } | ||
587 | }; | ||
588 | |||
589 | static struct ctl_table_header *ipmi_table_header; | ||
574 | #endif /* CONFIG_PROC_FS */ | 590 | #endif /* CONFIG_PROC_FS */ |
575 | 591 | ||
576 | /* | 592 | /* |
@@ -578,42 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer, | |||
578 | */ | 594 | */ |
579 | static int ipmi_poweroff_init (void) | 595 | static int ipmi_poweroff_init (void) |
580 | { | 596 | { |
581 | int rv; | 597 | int rv; |
582 | struct proc_dir_entry *file; | ||
583 | 598 | ||
584 | printk ("Copyright (C) 2004 MontaVista Software -" | 599 | printk ("Copyright (C) 2004 MontaVista Software -" |
585 | " IPMI Powerdown via sys_reboot version " | 600 | " IPMI Powerdown via sys_reboot.\n"); |
586 | IPMI_POWEROFF_VERSION ".\n"); | 601 | |
587 | 602 | if (poweroff_powercycle) | |
588 | switch (poweroff_control) { | 603 | printk(KERN_INFO PFX "Power cycle is enabled.\n"); |
589 | case IPMI_CHASSIS_POWER_CYCLE: | 604 | |
590 | printk(KERN_INFO PFX "Power cycle is enabled.\n"); | 605 | #ifdef CONFIG_PROC_FS |
591 | break; | 606 | ipmi_table_header = register_sysctl_table(ipmi_root_table, 1); |
592 | 607 | if (!ipmi_table_header) { | |
593 | case IPMI_CHASSIS_POWER_DOWN: | 608 | printk(KERN_ERR PFX "Unable to register powercycle sysctl\n"); |
594 | default: | 609 | rv = -ENOMEM; |
595 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 610 | goto out_err; |
596 | break; | ||
597 | } | 611 | } |
612 | #endif | ||
598 | 613 | ||
614 | #ifdef CONFIG_PROC_FS | ||
599 | rv = ipmi_smi_watcher_register(&smi_watcher); | 615 | rv = ipmi_smi_watcher_register(&smi_watcher); |
616 | #endif | ||
600 | if (rv) { | 617 | if (rv) { |
618 | unregister_sysctl_table(ipmi_table_header); | ||
601 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); | 619 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); |
602 | goto out_err; | 620 | goto out_err; |
603 | } | 621 | } |
604 | 622 | ||
605 | #ifdef CONFIG_PROC_FS | ||
606 | file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); | ||
607 | if (!file) { | ||
608 | printk(KERN_ERR PFX "Unable to create proc power control\n"); | ||
609 | } else { | ||
610 | file->nlink = 1; | ||
611 | file->read_proc = proc_read_chassctrl; | ||
612 | file->write_proc = proc_write_chassctrl; | ||
613 | file->owner = THIS_MODULE; | ||
614 | } | ||
615 | #endif | ||
616 | |||
617 | out_err: | 623 | out_err: |
618 | return rv; | 624 | return rv; |
619 | } | 625 | } |
@@ -624,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void) | |||
624 | int rv; | 630 | int rv; |
625 | 631 | ||
626 | #ifdef CONFIG_PROC_FS | 632 | #ifdef CONFIG_PROC_FS |
627 | remove_proc_entry("poweroff_control", proc_ipmi_root); | 633 | unregister_sysctl_table(ipmi_table_header); |
628 | #endif | 634 | #endif |
629 | 635 | ||
630 | ipmi_smi_watcher_unregister(&smi_watcher); | 636 | ipmi_smi_watcher_unregister(&smi_watcher); |
@@ -642,3 +648,5 @@ module_exit(ipmi_poweroff_cleanup); | |||
642 | 648 | ||
643 | module_init(ipmi_poweroff_init); | 649 | module_init(ipmi_poweroff_init); |
644 | MODULE_LICENSE("GPL"); | 650 | MODULE_LICENSE("GPL"); |
651 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
652 | MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot"); | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index adbec73b80a6..278f84104996 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -61,11 +61,11 @@ | |||
61 | # endif | 61 | # endif |
62 | static inline void add_usec_to_timer(struct timer_list *t, long v) | 62 | static inline void add_usec_to_timer(struct timer_list *t, long v) |
63 | { | 63 | { |
64 | t->sub_expires += nsec_to_arch_cycle(v * 1000); | 64 | t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000); |
65 | while (t->sub_expires >= arch_cycles_per_jiffy) | 65 | while (t->arch_cycle_expires >= arch_cycles_per_jiffy) |
66 | { | 66 | { |
67 | t->expires++; | 67 | t->expires++; |
68 | t->sub_expires -= arch_cycles_per_jiffy; | 68 | t->arch_cycle_expires -= arch_cycles_per_jiffy; |
69 | } | 69 | } |
70 | } | 70 | } |
71 | #endif | 71 | #endif |
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) | |||
75 | #include <asm/io.h> | 75 | #include <asm/io.h> |
76 | #include "ipmi_si_sm.h" | 76 | #include "ipmi_si_sm.h" |
77 | #include <linux/init.h> | 77 | #include <linux/init.h> |
78 | 78 | #include <linux/dmi.h> | |
79 | #define IPMI_SI_VERSION "v33" | ||
80 | 79 | ||
81 | /* Measure times between events in the driver. */ | 80 | /* Measure times between events in the driver. */ |
82 | #undef DEBUG_TIMING | 81 | #undef DEBUG_TIMING |
@@ -109,6 +108,21 @@ enum si_type { | |||
109 | SI_KCS, SI_SMIC, SI_BT | 108 | SI_KCS, SI_SMIC, SI_BT |
110 | }; | 109 | }; |
111 | 110 | ||
111 | struct ipmi_device_id { | ||
112 | unsigned char device_id; | ||
113 | unsigned char device_revision; | ||
114 | unsigned char firmware_revision_1; | ||
115 | unsigned char firmware_revision_2; | ||
116 | unsigned char ipmi_version; | ||
117 | unsigned char additional_device_support; | ||
118 | unsigned char manufacturer_id[3]; | ||
119 | unsigned char product_id[2]; | ||
120 | unsigned char aux_firmware_revision[4]; | ||
121 | } __attribute__((packed)); | ||
122 | |||
123 | #define ipmi_version_major(v) ((v)->ipmi_version & 0xf) | ||
124 | #define ipmi_version_minor(v) ((v)->ipmi_version >> 4) | ||
125 | |||
112 | struct smi_info | 126 | struct smi_info |
113 | { | 127 | { |
114 | ipmi_smi_t intf; | 128 | ipmi_smi_t intf; |
@@ -131,12 +145,24 @@ struct smi_info | |||
131 | void (*irq_cleanup)(struct smi_info *info); | 145 | void (*irq_cleanup)(struct smi_info *info); |
132 | unsigned int io_size; | 146 | unsigned int io_size; |
133 | 147 | ||
148 | /* Per-OEM handler, called from handle_flags(). | ||
149 | Returns 1 when handle_flags() needs to be re-run | ||
150 | or 0 indicating it set si_state itself. | ||
151 | */ | ||
152 | int (*oem_data_avail_handler)(struct smi_info *smi_info); | ||
153 | |||
134 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN | 154 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN |
135 | is set to hold the flags until we are done handling everything | 155 | is set to hold the flags until we are done handling everything |
136 | from the flags. */ | 156 | from the flags. */ |
137 | #define RECEIVE_MSG_AVAIL 0x01 | 157 | #define RECEIVE_MSG_AVAIL 0x01 |
138 | #define EVENT_MSG_BUFFER_FULL 0x02 | 158 | #define EVENT_MSG_BUFFER_FULL 0x02 |
139 | #define WDT_PRE_TIMEOUT_INT 0x08 | 159 | #define WDT_PRE_TIMEOUT_INT 0x08 |
160 | #define OEM0_DATA_AVAIL 0x20 | ||
161 | #define OEM1_DATA_AVAIL 0x40 | ||
162 | #define OEM2_DATA_AVAIL 0x80 | ||
163 | #define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \ | ||
164 | OEM1_DATA_AVAIL | \ | ||
165 | OEM2_DATA_AVAIL) | ||
140 | unsigned char msg_flags; | 166 | unsigned char msg_flags; |
141 | 167 | ||
142 | /* If set to true, this will request events the next time the | 168 | /* If set to true, this will request events the next time the |
@@ -175,11 +201,7 @@ struct smi_info | |||
175 | interrupts. */ | 201 | interrupts. */ |
176 | int interrupt_disabled; | 202 | int interrupt_disabled; |
177 | 203 | ||
178 | unsigned char ipmi_si_dev_rev; | 204 | struct ipmi_device_id device_id; |
179 | unsigned char ipmi_si_fw_rev_major; | ||
180 | unsigned char ipmi_si_fw_rev_minor; | ||
181 | unsigned char ipmi_version_major; | ||
182 | unsigned char ipmi_version_minor; | ||
183 | 205 | ||
184 | /* Slave address, could be reported from DMI. */ | 206 | /* Slave address, could be reported from DMI. */ |
185 | unsigned char slave_addr; | 207 | unsigned char slave_addr; |
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
245 | entry = smi_info->xmit_msgs.next; | 267 | entry = smi_info->xmit_msgs.next; |
246 | } | 268 | } |
247 | 269 | ||
248 | if (!entry) { | 270 | if (! entry) { |
249 | smi_info->curr_msg = NULL; | 271 | smi_info->curr_msg = NULL; |
250 | rv = SI_SM_IDLE; | 272 | rv = SI_SM_IDLE; |
251 | } else { | 273 | } else { |
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
306 | memory, we will re-enable the interrupt. */ | 328 | memory, we will re-enable the interrupt. */ |
307 | static inline void disable_si_irq(struct smi_info *smi_info) | 329 | static inline void disable_si_irq(struct smi_info *smi_info) |
308 | { | 330 | { |
309 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 331 | if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { |
310 | disable_irq_nosync(smi_info->irq); | 332 | disable_irq_nosync(smi_info->irq); |
311 | smi_info->interrupt_disabled = 1; | 333 | smi_info->interrupt_disabled = 1; |
312 | } | 334 | } |
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info) | |||
322 | 344 | ||
323 | static void handle_flags(struct smi_info *smi_info) | 345 | static void handle_flags(struct smi_info *smi_info) |
324 | { | 346 | { |
347 | retry: | ||
325 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { | 348 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { |
326 | /* Watchdog pre-timeout */ | 349 | /* Watchdog pre-timeout */ |
327 | spin_lock(&smi_info->count_lock); | 350 | spin_lock(&smi_info->count_lock); |
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
336 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 359 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
337 | /* Messages available. */ | 360 | /* Messages available. */ |
338 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 361 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
339 | if (!smi_info->curr_msg) { | 362 | if (! smi_info->curr_msg) { |
340 | disable_si_irq(smi_info); | 363 | disable_si_irq(smi_info); |
341 | smi_info->si_state = SI_NORMAL; | 364 | smi_info->si_state = SI_NORMAL; |
342 | return; | 365 | return; |
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
355 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { | 378 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { |
356 | /* Events available. */ | 379 | /* Events available. */ |
357 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 380 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
358 | if (!smi_info->curr_msg) { | 381 | if (! smi_info->curr_msg) { |
359 | disable_si_irq(smi_info); | 382 | disable_si_irq(smi_info); |
360 | smi_info->si_state = SI_NORMAL; | 383 | smi_info->si_state = SI_NORMAL; |
361 | return; | 384 | return; |
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info) | |||
371 | smi_info->curr_msg->data, | 394 | smi_info->curr_msg->data, |
372 | smi_info->curr_msg->data_size); | 395 | smi_info->curr_msg->data_size); |
373 | smi_info->si_state = SI_GETTING_EVENTS; | 396 | smi_info->si_state = SI_GETTING_EVENTS; |
397 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { | ||
398 | if (smi_info->oem_data_avail_handler) | ||
399 | if (smi_info->oem_data_avail_handler(smi_info)) | ||
400 | goto retry; | ||
374 | } else { | 401 | } else { |
375 | smi_info->si_state = SI_NORMAL; | 402 | smi_info->si_state = SI_NORMAL; |
376 | } | 403 | } |
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
387 | #endif | 414 | #endif |
388 | switch (smi_info->si_state) { | 415 | switch (smi_info->si_state) { |
389 | case SI_NORMAL: | 416 | case SI_NORMAL: |
390 | if (!smi_info->curr_msg) | 417 | if (! smi_info->curr_msg) |
391 | break; | 418 | break; |
392 | 419 | ||
393 | smi_info->curr_msg->rsp_size | 420 | smi_info->curr_msg->rsp_size |
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info) | |||
761 | #if defined(CONFIG_HIGH_RES_TIMERS) | 788 | #if defined(CONFIG_HIGH_RES_TIMERS) |
762 | unsigned long flags; | 789 | unsigned long flags; |
763 | unsigned long jiffies_now; | 790 | unsigned long jiffies_now; |
791 | unsigned long seq; | ||
764 | 792 | ||
765 | if (del_timer(&(smi_info->si_timer))) { | 793 | if (del_timer(&(smi_info->si_timer))) { |
766 | /* If we don't delete the timer, then it will go off | 794 | /* If we don't delete the timer, then it will go off |
767 | immediately, anyway. So we only process if we | 795 | immediately, anyway. So we only process if we |
768 | actually delete the timer. */ | 796 | actually delete the timer. */ |
769 | 797 | ||
770 | /* We already have irqsave on, so no need for it | 798 | do { |
771 | here. */ | 799 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
772 | read_lock(&xtime_lock); | 800 | jiffies_now = jiffies; |
773 | jiffies_now = jiffies; | 801 | smi_info->si_timer.expires = jiffies_now; |
774 | smi_info->si_timer.expires = jiffies_now; | 802 | smi_info->si_timer.arch_cycle_expires |
775 | smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now); | 803 | = get_arch_cycles(jiffies_now); |
804 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
776 | 805 | ||
777 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 806 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
778 | 807 | ||
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data) | |||
826 | /* If the state machine asks for a short delay, then shorten | 855 | /* If the state machine asks for a short delay, then shorten |
827 | the timer timeout. */ | 856 | the timer timeout. */ |
828 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 857 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
858 | #if defined(CONFIG_HIGH_RES_TIMERS) | ||
859 | unsigned long seq; | ||
860 | #endif | ||
829 | spin_lock_irqsave(&smi_info->count_lock, flags); | 861 | spin_lock_irqsave(&smi_info->count_lock, flags); |
830 | smi_info->short_timeouts++; | 862 | smi_info->short_timeouts++; |
831 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 863 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
832 | #if defined(CONFIG_HIGH_RES_TIMERS) | 864 | #if defined(CONFIG_HIGH_RES_TIMERS) |
833 | read_lock(&xtime_lock); | 865 | do { |
834 | smi_info->si_timer.expires = jiffies; | 866 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
835 | smi_info->si_timer.sub_expires | 867 | smi_info->si_timer.expires = jiffies; |
836 | = get_arch_cycles(smi_info->si_timer.expires); | 868 | smi_info->si_timer.arch_cycle_expires |
837 | read_unlock(&xtime_lock); | 869 | = get_arch_cycles(smi_info->si_timer.expires); |
870 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
838 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 871 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
839 | #else | 872 | #else |
840 | smi_info->si_timer.expires = jiffies + 1; | 873 | smi_info->si_timer.expires = jiffies + 1; |
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data) | |||
845 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 878 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
846 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 879 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
847 | #if defined(CONFIG_HIGH_RES_TIMERS) | 880 | #if defined(CONFIG_HIGH_RES_TIMERS) |
848 | smi_info->si_timer.sub_expires = 0; | 881 | smi_info->si_timer.arch_cycle_expires = 0; |
849 | #endif | 882 | #endif |
850 | } | 883 | } |
851 | 884 | ||
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1014 | { | 1047 | { |
1015 | int rv; | 1048 | int rv; |
1016 | 1049 | ||
1017 | if (!info->irq) | 1050 | if (! info->irq) |
1018 | return 0; | 1051 | return 0; |
1019 | 1052 | ||
1020 | if (info->si_type == SI_BT) { | 1053 | if (info->si_type == SI_BT) { |
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1023 | SA_INTERRUPT, | 1056 | SA_INTERRUPT, |
1024 | DEVICE_NAME, | 1057 | DEVICE_NAME, |
1025 | info); | 1058 | info); |
1026 | if (!rv) | 1059 | if (! rv) |
1027 | /* Enable the interrupt in the BT interface. */ | 1060 | /* Enable the interrupt in the BT interface. */ |
1028 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, | 1061 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, |
1029 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); | 1062 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); |
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1048 | 1081 | ||
1049 | static void std_irq_cleanup(struct smi_info *info) | 1082 | static void std_irq_cleanup(struct smi_info *info) |
1050 | { | 1083 | { |
1051 | if (!info->irq) | 1084 | if (! info->irq) |
1052 | return; | 1085 | return; |
1053 | 1086 | ||
1054 | if (info->si_type == SI_BT) | 1087 | if (info->si_type == SI_BT) |
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info) | |||
1121 | unsigned int *addr = info->io.info; | 1154 | unsigned int *addr = info->io.info; |
1122 | int mapsize; | 1155 | int mapsize; |
1123 | 1156 | ||
1124 | if (!addr || (!*addr)) | 1157 | if (! addr || (! *addr)) |
1125 | return -ENODEV; | 1158 | return -ENODEV; |
1126 | 1159 | ||
1127 | info->io_cleanup = port_cleanup; | 1160 | info->io_cleanup = port_cleanup; |
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1164 | { | 1197 | { |
1165 | struct smi_info *info; | 1198 | struct smi_info *info; |
1166 | 1199 | ||
1167 | if (!ports[intf_num]) | 1200 | if (! ports[intf_num]) |
1168 | return -ENODEV; | 1201 | return -ENODEV; |
1169 | 1202 | ||
1170 | if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, | 1203 | if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, |
1171 | ports[intf_num])) | 1204 | ports[intf_num])) |
1172 | return -ENODEV; | 1205 | return -ENODEV; |
1173 | 1206 | ||
1174 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1207 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1175 | if (!info) { | 1208 | if (! info) { |
1176 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); | 1209 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); |
1177 | return -ENOMEM; | 1210 | return -ENOMEM; |
1178 | } | 1211 | } |
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1182 | info->io.info = &(ports[intf_num]); | 1215 | info->io.info = &(ports[intf_num]); |
1183 | info->io.addr = NULL; | 1216 | info->io.addr = NULL; |
1184 | info->io.regspacing = regspacings[intf_num]; | 1217 | info->io.regspacing = regspacings[intf_num]; |
1185 | if (!info->io.regspacing) | 1218 | if (! info->io.regspacing) |
1186 | info->io.regspacing = DEFAULT_REGSPACING; | 1219 | info->io.regspacing = DEFAULT_REGSPACING; |
1187 | info->io.regsize = regsizes[intf_num]; | 1220 | info->io.regsize = regsizes[intf_num]; |
1188 | if (!info->io.regsize) | 1221 | if (! info->io.regsize) |
1189 | info->io.regsize = DEFAULT_REGSPACING; | 1222 | info->io.regsize = DEFAULT_REGSPACING; |
1190 | info->io.regshift = regshifts[intf_num]; | 1223 | info->io.regshift = regshifts[intf_num]; |
1191 | info->irq = 0; | 1224 | info->irq = 0; |
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info) | |||
1270 | unsigned long *addr = info->io.info; | 1303 | unsigned long *addr = info->io.info; |
1271 | int mapsize; | 1304 | int mapsize; |
1272 | 1305 | ||
1273 | if (!addr || (!*addr)) | 1306 | if (! addr || (! *addr)) |
1274 | return -ENODEV; | 1307 | return -ENODEV; |
1275 | 1308 | ||
1276 | info->io_cleanup = mem_cleanup; | 1309 | info->io_cleanup = mem_cleanup; |
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1325 | { | 1358 | { |
1326 | struct smi_info *info; | 1359 | struct smi_info *info; |
1327 | 1360 | ||
1328 | if (!addrs[intf_num]) | 1361 | if (! addrs[intf_num]) |
1329 | return -ENODEV; | 1362 | return -ENODEV; |
1330 | 1363 | ||
1331 | if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, | 1364 | if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, |
1332 | addrs[intf_num])) | 1365 | addrs[intf_num])) |
1333 | return -ENODEV; | 1366 | return -ENODEV; |
1334 | 1367 | ||
1335 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1368 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1336 | if (!info) { | 1369 | if (! info) { |
1337 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); | 1370 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); |
1338 | return -ENOMEM; | 1371 | return -ENOMEM; |
1339 | } | 1372 | } |
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1343 | info->io.info = &addrs[intf_num]; | 1376 | info->io.info = &addrs[intf_num]; |
1344 | info->io.addr = NULL; | 1377 | info->io.addr = NULL; |
1345 | info->io.regspacing = regspacings[intf_num]; | 1378 | info->io.regspacing = regspacings[intf_num]; |
1346 | if (!info->io.regspacing) | 1379 | if (! info->io.regspacing) |
1347 | info->io.regspacing = DEFAULT_REGSPACING; | 1380 | info->io.regspacing = DEFAULT_REGSPACING; |
1348 | info->io.regsize = regsizes[intf_num]; | 1381 | info->io.regsize = regsizes[intf_num]; |
1349 | if (!info->io.regsize) | 1382 | if (! info->io.regsize) |
1350 | info->io.regsize = DEFAULT_REGSPACING; | 1383 | info->io.regsize = DEFAULT_REGSPACING; |
1351 | info->io.regshift = regshifts[intf_num]; | 1384 | info->io.regshift = regshifts[intf_num]; |
1352 | info->irq = 0; | 1385 | info->irq = 0; |
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1404 | { | 1437 | { |
1405 | acpi_status status; | 1438 | acpi_status status; |
1406 | 1439 | ||
1407 | if (!info->irq) | 1440 | if (! info->irq) |
1408 | return 0; | 1441 | return 0; |
1409 | 1442 | ||
1410 | /* FIXME - is level triggered right? */ | 1443 | /* FIXME - is level triggered right? */ |
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1428 | 1461 | ||
1429 | static void acpi_gpe_irq_cleanup(struct smi_info *info) | 1462 | static void acpi_gpe_irq_cleanup(struct smi_info *info) |
1430 | { | 1463 | { |
1431 | if (!info->irq) | 1464 | if (! info->irq) |
1432 | return; | 1465 | return; |
1433 | 1466 | ||
1434 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); | 1467 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); |
@@ -1507,10 +1540,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1507 | addr_space = IPMI_MEM_ADDR_SPACE; | 1540 | addr_space = IPMI_MEM_ADDR_SPACE; |
1508 | else | 1541 | else |
1509 | addr_space = IPMI_IO_ADDR_SPACE; | 1542 | addr_space = IPMI_IO_ADDR_SPACE; |
1510 | if (!is_new_interface(-1, addr_space, spmi->addr.address)) | 1543 | if (! is_new_interface(-1, addr_space, spmi->addr.address)) |
1511 | return -ENODEV; | 1544 | return -ENODEV; |
1512 | 1545 | ||
1513 | if (!spmi->addr.register_bit_width) { | 1546 | if (! spmi->addr.register_bit_width) { |
1514 | acpi_failure = 1; | 1547 | acpi_failure = 1; |
1515 | return -ENODEV; | 1548 | return -ENODEV; |
1516 | } | 1549 | } |
@@ -1537,7 +1570,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1537 | } | 1570 | } |
1538 | 1571 | ||
1539 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1572 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1540 | if (!info) { | 1573 | if (! info) { |
1541 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | 1574 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); |
1542 | return -ENOMEM; | 1575 | return -ENOMEM; |
1543 | } | 1576 | } |
@@ -1613,22 +1646,15 @@ typedef struct dmi_ipmi_data | |||
1613 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; | 1646 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; |
1614 | static int dmi_data_entries; | 1647 | static int dmi_data_entries; |
1615 | 1648 | ||
1616 | typedef struct dmi_header | 1649 | static int __init decode_dmi(struct dmi_header *dm, int intf_num) |
1617 | { | ||
1618 | u8 type; | ||
1619 | u8 length; | ||
1620 | u16 handle; | ||
1621 | } dmi_header_t; | ||
1622 | |||
1623 | static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | ||
1624 | { | 1650 | { |
1625 | u8 __iomem *data = (u8 __iomem *)dm; | 1651 | u8 *data = (u8 *)dm; |
1626 | unsigned long base_addr; | 1652 | unsigned long base_addr; |
1627 | u8 reg_spacing; | 1653 | u8 reg_spacing; |
1628 | u8 len = readb(&dm->length); | 1654 | u8 len = dm->length; |
1629 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1655 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1630 | 1656 | ||
1631 | ipmi_data->type = readb(&data[4]); | 1657 | ipmi_data->type = data[4]; |
1632 | 1658 | ||
1633 | memcpy(&base_addr, data+8, sizeof(unsigned long)); | 1659 | memcpy(&base_addr, data+8, sizeof(unsigned long)); |
1634 | if (len >= 0x11) { | 1660 | if (len >= 0x11) { |
@@ -1643,12 +1669,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1643 | } | 1669 | } |
1644 | /* If bit 4 of byte 0x10 is set, then the lsb for the address | 1670 | /* If bit 4 of byte 0x10 is set, then the lsb for the address |
1645 | is odd. */ | 1671 | is odd. */ |
1646 | ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4); | 1672 | ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); |
1647 | 1673 | ||
1648 | ipmi_data->irq = readb(&data[0x11]); | 1674 | ipmi_data->irq = data[0x11]; |
1649 | 1675 | ||
1650 | /* The top two bits of byte 0x10 hold the register spacing. */ | 1676 | /* The top two bits of byte 0x10 hold the register spacing. */ |
1651 | reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6; | 1677 | reg_spacing = (data[0x10] & 0xC0) >> 6; |
1652 | switch(reg_spacing){ | 1678 | switch(reg_spacing){ |
1653 | case 0x00: /* Byte boundaries */ | 1679 | case 0x00: /* Byte boundaries */ |
1654 | ipmi_data->offset = 1; | 1680 | ipmi_data->offset = 1; |
@@ -1676,7 +1702,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1676 | ipmi_data->offset = 1; | 1702 | ipmi_data->offset = 1; |
1677 | } | 1703 | } |
1678 | 1704 | ||
1679 | ipmi_data->slave_addr = readb(&data[6]); | 1705 | ipmi_data->slave_addr = data[6]; |
1680 | 1706 | ||
1681 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { | 1707 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { |
1682 | dmi_data_entries++; | 1708 | dmi_data_entries++; |
@@ -1688,94 +1714,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1688 | return -1; | 1714 | return -1; |
1689 | } | 1715 | } |
1690 | 1716 | ||
1691 | static int dmi_table(u32 base, int len, int num) | 1717 | static void __init dmi_find_bmc(void) |
1692 | { | 1718 | { |
1693 | u8 __iomem *buf; | 1719 | struct dmi_device *dev = NULL; |
1694 | struct dmi_header __iomem *dm; | ||
1695 | u8 __iomem *data; | ||
1696 | int i=1; | ||
1697 | int status=-1; | ||
1698 | int intf_num = 0; | 1720 | int intf_num = 0; |
1699 | 1721 | ||
1700 | buf = ioremap(base, len); | 1722 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { |
1701 | if(buf==NULL) | 1723 | if (intf_num >= SI_MAX_DRIVERS) |
1702 | return -1; | 1724 | break; |
1703 | |||
1704 | data = buf; | ||
1705 | |||
1706 | while(i<num && (data - buf) < len) | ||
1707 | { | ||
1708 | dm=(dmi_header_t __iomem *)data; | ||
1709 | |||
1710 | if((data-buf+readb(&dm->length)) >= len) | ||
1711 | break; | ||
1712 | |||
1713 | if (readb(&dm->type) == 38) { | ||
1714 | if (decode_dmi(dm, intf_num) == 0) { | ||
1715 | intf_num++; | ||
1716 | if (intf_num >= SI_MAX_DRIVERS) | ||
1717 | break; | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | data+=readb(&dm->length); | ||
1722 | while((data-buf) < len && (readb(data)||readb(data+1))) | ||
1723 | data++; | ||
1724 | data+=2; | ||
1725 | i++; | ||
1726 | } | ||
1727 | iounmap(buf); | ||
1728 | |||
1729 | return status; | ||
1730 | } | ||
1731 | |||
1732 | static inline int dmi_checksum(u8 *buf) | ||
1733 | { | ||
1734 | u8 sum=0; | ||
1735 | int a; | ||
1736 | |||
1737 | for(a=0; a<15; a++) | ||
1738 | sum+=buf[a]; | ||
1739 | return (sum==0); | ||
1740 | } | ||
1741 | |||
1742 | static int dmi_decode(void) | ||
1743 | { | ||
1744 | u8 buf[15]; | ||
1745 | u32 fp=0xF0000; | ||
1746 | |||
1747 | #ifdef CONFIG_SIMNOW | ||
1748 | return -1; | ||
1749 | #endif | ||
1750 | |||
1751 | while(fp < 0xFFFFF) | ||
1752 | { | ||
1753 | isa_memcpy_fromio(buf, fp, 15); | ||
1754 | if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) | ||
1755 | { | ||
1756 | u16 num=buf[13]<<8|buf[12]; | ||
1757 | u16 len=buf[7]<<8|buf[6]; | ||
1758 | u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; | ||
1759 | 1725 | ||
1760 | if(dmi_table(base, len, num) == 0) | 1726 | decode_dmi((struct dmi_header *) dev->device_data, intf_num++); |
1761 | return 0; | ||
1762 | } | ||
1763 | fp+=16; | ||
1764 | } | 1727 | } |
1765 | |||
1766 | return -1; | ||
1767 | } | 1728 | } |
1768 | 1729 | ||
1769 | static int try_init_smbios(int intf_num, struct smi_info **new_info) | 1730 | static int try_init_smbios(int intf_num, struct smi_info **new_info) |
1770 | { | 1731 | { |
1771 | struct smi_info *info; | 1732 | struct smi_info *info; |
1772 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1733 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1773 | char *io_type; | 1734 | char *io_type; |
1774 | 1735 | ||
1775 | if (intf_num >= dmi_data_entries) | 1736 | if (intf_num >= dmi_data_entries) |
1776 | return -ENODEV; | 1737 | return -ENODEV; |
1777 | 1738 | ||
1778 | switch(ipmi_data->type) { | 1739 | switch (ipmi_data->type) { |
1779 | case 0x01: /* KCS */ | 1740 | case 0x01: /* KCS */ |
1780 | si_type[intf_num] = "kcs"; | 1741 | si_type[intf_num] = "kcs"; |
1781 | break; | 1742 | break; |
@@ -1790,7 +1751,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1790 | } | 1751 | } |
1791 | 1752 | ||
1792 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1753 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1793 | if (!info) { | 1754 | if (! info) { |
1794 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); | 1755 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); |
1795 | return -ENOMEM; | 1756 | return -ENOMEM; |
1796 | } | 1757 | } |
@@ -1814,7 +1775,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1814 | 1775 | ||
1815 | regspacings[intf_num] = ipmi_data->offset; | 1776 | regspacings[intf_num] = ipmi_data->offset; |
1816 | info->io.regspacing = regspacings[intf_num]; | 1777 | info->io.regspacing = regspacings[intf_num]; |
1817 | if (!info->io.regspacing) | 1778 | if (! info->io.regspacing) |
1818 | info->io.regspacing = DEFAULT_REGSPACING; | 1779 | info->io.regspacing = DEFAULT_REGSPACING; |
1819 | info->io.regsize = DEFAULT_REGSPACING; | 1780 | info->io.regsize = DEFAULT_REGSPACING; |
1820 | info->io.regshift = regshifts[intf_num]; | 1781 | info->io.regshift = regshifts[intf_num]; |
@@ -1856,14 +1817,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1856 | 1817 | ||
1857 | pci_smic_checked = 1; | 1818 | pci_smic_checked = 1; |
1858 | 1819 | ||
1859 | if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, | 1820 | pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); |
1860 | NULL))) | 1821 | if (! pci_dev) { |
1861 | ; | 1822 | pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); |
1862 | else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && | 1823 | if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) |
1863 | pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) | 1824 | fe_rmc = 1; |
1864 | fe_rmc = 1; | 1825 | else |
1865 | else | 1826 | return -ENODEV; |
1866 | return -ENODEV; | 1827 | } |
1867 | 1828 | ||
1868 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); | 1829 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); |
1869 | if (error) | 1830 | if (error) |
@@ -1876,7 +1837,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1876 | } | 1837 | } |
1877 | 1838 | ||
1878 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ | 1839 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ |
1879 | if (!(base_addr & 0x0001)) | 1840 | if (! (base_addr & 0x0001)) |
1880 | { | 1841 | { |
1881 | pci_dev_put(pci_dev); | 1842 | pci_dev_put(pci_dev); |
1882 | printk(KERN_ERR | 1843 | printk(KERN_ERR |
@@ -1886,17 +1847,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1886 | } | 1847 | } |
1887 | 1848 | ||
1888 | base_addr &= 0xFFFE; | 1849 | base_addr &= 0xFFFE; |
1889 | if (!fe_rmc) | 1850 | if (! fe_rmc) |
1890 | /* Data register starts at base address + 1 in eRMC */ | 1851 | /* Data register starts at base address + 1 in eRMC */ |
1891 | ++base_addr; | 1852 | ++base_addr; |
1892 | 1853 | ||
1893 | if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { | 1854 | if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { |
1894 | pci_dev_put(pci_dev); | 1855 | pci_dev_put(pci_dev); |
1895 | return -ENODEV; | 1856 | return -ENODEV; |
1896 | } | 1857 | } |
1897 | 1858 | ||
1898 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1859 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1899 | if (!info) { | 1860 | if (! info) { |
1900 | pci_dev_put(pci_dev); | 1861 | pci_dev_put(pci_dev); |
1901 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); | 1862 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); |
1902 | return -ENOMEM; | 1863 | return -ENOMEM; |
@@ -1907,7 +1868,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1907 | ports[intf_num] = base_addr; | 1868 | ports[intf_num] = base_addr; |
1908 | info->io.info = &(ports[intf_num]); | 1869 | info->io.info = &(ports[intf_num]); |
1909 | info->io.regspacing = regspacings[intf_num]; | 1870 | info->io.regspacing = regspacings[intf_num]; |
1910 | if (!info->io.regspacing) | 1871 | if (! info->io.regspacing) |
1911 | info->io.regspacing = DEFAULT_REGSPACING; | 1872 | info->io.regspacing = DEFAULT_REGSPACING; |
1912 | info->io.regsize = DEFAULT_REGSPACING; | 1873 | info->io.regsize = DEFAULT_REGSPACING; |
1913 | info->io.regshift = regshifts[intf_num]; | 1874 | info->io.regshift = regshifts[intf_num]; |
@@ -1928,7 +1889,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1928 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) | 1889 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) |
1929 | { | 1890 | { |
1930 | #ifdef CONFIG_PCI | 1891 | #ifdef CONFIG_PCI |
1931 | if (find_pci_smic(intf_num, new_info)==0) | 1892 | if (find_pci_smic(intf_num, new_info) == 0) |
1932 | return 0; | 1893 | return 0; |
1933 | #endif | 1894 | #endif |
1934 | /* Include other methods here. */ | 1895 | /* Include other methods here. */ |
@@ -1946,7 +1907,7 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1946 | int rv = 0; | 1907 | int rv = 0; |
1947 | 1908 | ||
1948 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | 1909 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); |
1949 | if (!resp) | 1910 | if (! resp) |
1950 | return -ENOMEM; | 1911 | return -ENOMEM; |
1951 | 1912 | ||
1952 | /* Do a Get Device ID command, since it comes back with some | 1913 | /* Do a Get Device ID command, since it comes back with some |
@@ -1995,11 +1956,8 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1995 | } | 1956 | } |
1996 | 1957 | ||
1997 | /* Record info from the get device id, in case we need it. */ | 1958 | /* Record info from the get device id, in case we need it. */ |
1998 | smi_info->ipmi_si_dev_rev = resp[4] & 0xf; | 1959 | memcpy(&smi_info->device_id, &resp[3], |
1999 | smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f; | 1960 | min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id))); |
2000 | smi_info->ipmi_si_fw_rev_minor = resp[6]; | ||
2001 | smi_info->ipmi_version_major = resp[7] & 0xf; | ||
2002 | smi_info->ipmi_version_minor = resp[7] >> 4; | ||
2003 | 1961 | ||
2004 | out: | 1962 | out: |
2005 | kfree(resp); | 1963 | kfree(resp); |
@@ -2031,7 +1989,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2031 | struct smi_info *smi = data; | 1989 | struct smi_info *smi = data; |
2032 | 1990 | ||
2033 | out += sprintf(out, "interrupts_enabled: %d\n", | 1991 | out += sprintf(out, "interrupts_enabled: %d\n", |
2034 | smi->irq && !smi->interrupt_disabled); | 1992 | smi->irq && ! smi->interrupt_disabled); |
2035 | out += sprintf(out, "short_timeouts: %ld\n", | 1993 | out += sprintf(out, "short_timeouts: %ld\n", |
2036 | smi->short_timeouts); | 1994 | smi->short_timeouts); |
2037 | out += sprintf(out, "long_timeouts: %ld\n", | 1995 | out += sprintf(out, "long_timeouts: %ld\n", |
@@ -2060,6 +2018,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2060 | return (out - ((char *) page)); | 2018 | return (out - ((char *) page)); |
2061 | } | 2019 | } |
2062 | 2020 | ||
2021 | /* | ||
2022 | * oem_data_avail_to_receive_msg_avail | ||
2023 | * @info - smi_info structure with msg_flags set | ||
2024 | * | ||
2025 | * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL | ||
2026 | * Returns 1 indicating need to re-run handle_flags(). | ||
2027 | */ | ||
2028 | static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) | ||
2029 | { | ||
2030 | smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) | | ||
2031 | RECEIVE_MSG_AVAIL); | ||
2032 | return 1; | ||
2033 | } | ||
2034 | |||
2035 | /* | ||
2036 | * setup_dell_poweredge_oem_data_handler | ||
2037 | * @info - smi_info.device_id must be populated | ||
2038 | * | ||
2039 | * Systems that match, but have firmware version < 1.40 may assert | ||
2040 | * OEM0_DATA_AVAIL on their own, without being told via Set Flags that | ||
2041 | * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL | ||
2042 | * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags | ||
2043 | * as RECEIVE_MSG_AVAIL instead. | ||
2044 | * | ||
2045 | * As Dell has no plans to release IPMI 1.5 firmware that *ever* | ||
2046 | * assert the OEM[012] bits, and if it did, the driver would have to | ||
2047 | * change to handle that properly, we don't actually check for the | ||
2048 | * firmware version. | ||
2049 | * Device ID = 0x20 BMC on PowerEdge 8G servers | ||
2050 | * Device Revision = 0x80 | ||
2051 | * Firmware Revision1 = 0x01 BMC version 1.40 | ||
2052 | * Firmware Revision2 = 0x40 BCD encoded | ||
2053 | * IPMI Version = 0x51 IPMI 1.5 | ||
2054 | * Manufacturer ID = A2 02 00 Dell IANA | ||
2055 | * | ||
2056 | */ | ||
2057 | #define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 | ||
2058 | #define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 | ||
2059 | #define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 | ||
2060 | #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} | ||
2061 | static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) | ||
2062 | { | ||
2063 | struct ipmi_device_id *id = &smi_info->device_id; | ||
2064 | const char mfr[3]=DELL_IANA_MFR_ID; | ||
2065 | if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) | ||
2066 | && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID) | ||
2067 | && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV) | ||
2068 | && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION)) | ||
2069 | { | ||
2070 | smi_info->oem_data_avail_handler = | ||
2071 | oem_data_avail_to_receive_msg_avail; | ||
2072 | } | ||
2073 | } | ||
2074 | |||
2075 | /* | ||
2076 | * setup_oem_data_handler | ||
2077 | * @info - smi_info.device_id must be filled in already | ||
2078 | * | ||
2079 | * Fills in smi_info.device_id.oem_data_available_handler | ||
2080 | * when we know what function to use there. | ||
2081 | */ | ||
2082 | |||
2083 | static void setup_oem_data_handler(struct smi_info *smi_info) | ||
2084 | { | ||
2085 | setup_dell_poweredge_oem_data_handler(smi_info); | ||
2086 | } | ||
2087 | |||
2063 | /* Returns 0 if initialized, or negative on an error. */ | 2088 | /* Returns 0 if initialized, or negative on an error. */ |
2064 | static int init_one_smi(int intf_num, struct smi_info **smi) | 2089 | static int init_one_smi(int intf_num, struct smi_info **smi) |
2065 | { | 2090 | { |
@@ -2071,19 +2096,15 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2071 | if (rv) | 2096 | if (rv) |
2072 | rv = try_init_port(intf_num, &new_smi); | 2097 | rv = try_init_port(intf_num, &new_smi); |
2073 | #ifdef CONFIG_ACPI | 2098 | #ifdef CONFIG_ACPI |
2074 | if ((rv) && (si_trydefaults)) { | 2099 | if (rv && si_trydefaults) |
2075 | rv = try_init_acpi(intf_num, &new_smi); | 2100 | rv = try_init_acpi(intf_num, &new_smi); |
2076 | } | ||
2077 | #endif | 2101 | #endif |
2078 | #ifdef CONFIG_X86 | 2102 | #ifdef CONFIG_X86 |
2079 | if ((rv) && (si_trydefaults)) { | 2103 | if (rv && si_trydefaults) |
2080 | rv = try_init_smbios(intf_num, &new_smi); | 2104 | rv = try_init_smbios(intf_num, &new_smi); |
2081 | } | ||
2082 | #endif | 2105 | #endif |
2083 | if ((rv) && (si_trydefaults)) { | 2106 | if (rv && si_trydefaults) |
2084 | rv = try_init_plug_and_play(intf_num, &new_smi); | 2107 | rv = try_init_plug_and_play(intf_num, &new_smi); |
2085 | } | ||
2086 | |||
2087 | 2108 | ||
2088 | if (rv) | 2109 | if (rv) |
2089 | return rv; | 2110 | return rv; |
@@ -2093,7 +2114,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2093 | new_smi->si_sm = NULL; | 2114 | new_smi->si_sm = NULL; |
2094 | new_smi->handlers = NULL; | 2115 | new_smi->handlers = NULL; |
2095 | 2116 | ||
2096 | if (!new_smi->irq_setup) { | 2117 | if (! new_smi->irq_setup) { |
2097 | new_smi->irq = irqs[intf_num]; | 2118 | new_smi->irq = irqs[intf_num]; |
2098 | new_smi->irq_setup = std_irq_setup; | 2119 | new_smi->irq_setup = std_irq_setup; |
2099 | new_smi->irq_cleanup = std_irq_cleanup; | 2120 | new_smi->irq_cleanup = std_irq_cleanup; |
@@ -2127,7 +2148,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2127 | 2148 | ||
2128 | /* Allocate the state machine's data and initialize it. */ | 2149 | /* Allocate the state machine's data and initialize it. */ |
2129 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 2150 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
2130 | if (!new_smi->si_sm) { | 2151 | if (! new_smi->si_sm) { |
2131 | printk(" Could not allocate state machine memory\n"); | 2152 | printk(" Could not allocate state machine memory\n"); |
2132 | rv = -ENOMEM; | 2153 | rv = -ENOMEM; |
2133 | goto out_err; | 2154 | goto out_err; |
@@ -2158,6 +2179,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2158 | if (rv) | 2179 | if (rv) |
2159 | goto out_err; | 2180 | goto out_err; |
2160 | 2181 | ||
2182 | setup_oem_data_handler(new_smi); | ||
2183 | |||
2161 | /* Try to claim any interrupts. */ | 2184 | /* Try to claim any interrupts. */ |
2162 | new_smi->irq_setup(new_smi); | 2185 | new_smi->irq_setup(new_smi); |
2163 | 2186 | ||
@@ -2191,8 +2214,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2191 | 2214 | ||
2192 | rv = ipmi_register_smi(&handlers, | 2215 | rv = ipmi_register_smi(&handlers, |
2193 | new_smi, | 2216 | new_smi, |
2194 | new_smi->ipmi_version_major, | 2217 | ipmi_version_major(&new_smi->device_id), |
2195 | new_smi->ipmi_version_minor, | 2218 | ipmi_version_minor(&new_smi->device_id), |
2196 | new_smi->slave_addr, | 2219 | new_smi->slave_addr, |
2197 | &(new_smi->intf)); | 2220 | &(new_smi->intf)); |
2198 | if (rv) { | 2221 | if (rv) { |
@@ -2233,7 +2256,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2233 | 2256 | ||
2234 | /* Wait for the timer to stop. This avoids problems with race | 2257 | /* Wait for the timer to stop. This avoids problems with race |
2235 | conditions removing the timer here. */ | 2258 | conditions removing the timer here. */ |
2236 | while (!new_smi->timer_stopped) { | 2259 | while (! new_smi->timer_stopped) { |
2237 | set_current_state(TASK_UNINTERRUPTIBLE); | 2260 | set_current_state(TASK_UNINTERRUPTIBLE); |
2238 | schedule_timeout(1); | 2261 | schedule_timeout(1); |
2239 | } | 2262 | } |
@@ -2273,7 +2296,7 @@ static __init int init_ipmi_si(void) | |||
2273 | /* Parse out the si_type string into its components. */ | 2296 | /* Parse out the si_type string into its components. */ |
2274 | str = si_type_str; | 2297 | str = si_type_str; |
2275 | if (*str != '\0') { | 2298 | if (*str != '\0') { |
2276 | for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) { | 2299 | for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) { |
2277 | si_type[i] = str; | 2300 | si_type[i] = str; |
2278 | str = strchr(str, ','); | 2301 | str = strchr(str, ','); |
2279 | if (str) { | 2302 | if (str) { |
@@ -2285,22 +2308,14 @@ static __init int init_ipmi_si(void) | |||
2285 | } | 2308 | } |
2286 | } | 2309 | } |
2287 | 2310 | ||
2288 | printk(KERN_INFO "IPMI System Interface driver version " | 2311 | printk(KERN_INFO "IPMI System Interface driver.\n"); |
2289 | IPMI_SI_VERSION); | ||
2290 | if (kcs_smi_handlers.version) | ||
2291 | printk(", KCS version %s", kcs_smi_handlers.version); | ||
2292 | if (smic_smi_handlers.version) | ||
2293 | printk(", SMIC version %s", smic_smi_handlers.version); | ||
2294 | if (bt_smi_handlers.version) | ||
2295 | printk(", BT version %s", bt_smi_handlers.version); | ||
2296 | printk("\n"); | ||
2297 | 2312 | ||
2298 | #ifdef CONFIG_X86 | 2313 | #ifdef CONFIG_X86 |
2299 | dmi_decode(); | 2314 | dmi_find_bmc(); |
2300 | #endif | 2315 | #endif |
2301 | 2316 | ||
2302 | rv = init_one_smi(0, &(smi_infos[pos])); | 2317 | rv = init_one_smi(0, &(smi_infos[pos])); |
2303 | if (rv && !ports[0] && si_trydefaults) { | 2318 | if (rv && ! ports[0] && si_trydefaults) { |
2304 | /* If we are trying defaults and the initial port is | 2319 | /* If we are trying defaults and the initial port is |
2305 | not set, then set it. */ | 2320 | not set, then set it. */ |
2306 | si_type[0] = "kcs"; | 2321 | si_type[0] = "kcs"; |
@@ -2322,7 +2337,7 @@ static __init int init_ipmi_si(void) | |||
2322 | if (rv == 0) | 2337 | if (rv == 0) |
2323 | pos++; | 2338 | pos++; |
2324 | 2339 | ||
2325 | for (i=1; i < SI_MAX_PARMS; i++) { | 2340 | for (i = 1; i < SI_MAX_PARMS; i++) { |
2326 | rv = init_one_smi(i, &(smi_infos[pos])); | 2341 | rv = init_one_smi(i, &(smi_infos[pos])); |
2327 | if (rv == 0) | 2342 | if (rv == 0) |
2328 | pos++; | 2343 | pos++; |
@@ -2364,14 +2379,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) | |||
2364 | 2379 | ||
2365 | /* Wait for the timer to stop. This avoids problems with race | 2380 | /* Wait for the timer to stop. This avoids problems with race |
2366 | conditions removing the timer here. */ | 2381 | conditions removing the timer here. */ |
2367 | while (!to_clean->timer_stopped) { | 2382 | while (! to_clean->timer_stopped) { |
2368 | set_current_state(TASK_UNINTERRUPTIBLE); | 2383 | set_current_state(TASK_UNINTERRUPTIBLE); |
2369 | schedule_timeout(1); | 2384 | schedule_timeout(1); |
2370 | } | 2385 | } |
2371 | 2386 | ||
2372 | /* Interrupts and timeouts are stopped, now make sure the | 2387 | /* Interrupts and timeouts are stopped, now make sure the |
2373 | interface is in a clean state. */ | 2388 | interface is in a clean state. */ |
2374 | while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { | 2389 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
2375 | poll(to_clean); | 2390 | poll(to_clean); |
2376 | set_current_state(TASK_UNINTERRUPTIBLE); | 2391 | set_current_state(TASK_UNINTERRUPTIBLE); |
2377 | schedule_timeout(1); | 2392 | schedule_timeout(1); |
@@ -2395,13 +2410,15 @@ static __exit void cleanup_ipmi_si(void) | |||
2395 | { | 2410 | { |
2396 | int i; | 2411 | int i; |
2397 | 2412 | ||
2398 | if (!initialized) | 2413 | if (! initialized) |
2399 | return; | 2414 | return; |
2400 | 2415 | ||
2401 | for (i=0; i<SI_MAX_DRIVERS; i++) { | 2416 | for (i = 0; i < SI_MAX_DRIVERS; i++) { |
2402 | cleanup_one_si(smi_infos[i]); | 2417 | cleanup_one_si(smi_infos[i]); |
2403 | } | 2418 | } |
2404 | } | 2419 | } |
2405 | module_exit(cleanup_ipmi_si); | 2420 | module_exit(cleanup_ipmi_si); |
2406 | 2421 | ||
2407 | MODULE_LICENSE("GPL"); | 2422 | MODULE_LICENSE("GPL"); |
2423 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
2424 | MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces."); | ||
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index ae18747e670b..add2aa2732f0 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 46 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
47 | #include "ipmi_si_sm.h" | 47 | #include "ipmi_si_sm.h" |
48 | 48 | ||
49 | #define IPMI_SMIC_VERSION "v33" | ||
50 | |||
51 | /* smic_debug is a bit-field | 49 | /* smic_debug is a bit-field |
52 | * SMIC_DEBUG_ENABLE - turned on for now | 50 | * SMIC_DEBUG_ENABLE - turned on for now |
53 | * SMIC_DEBUG_MSG - commands and their responses | 51 | * SMIC_DEBUG_MSG - commands and their responses |
@@ -588,7 +586,6 @@ static int smic_size(void) | |||
588 | 586 | ||
589 | struct si_sm_handlers smic_smi_handlers = | 587 | struct si_sm_handlers smic_smi_handlers = |
590 | { | 588 | { |
591 | .version = IPMI_SMIC_VERSION, | ||
592 | .init_data = init_smic_data, | 589 | .init_data = init_smic_data, |
593 | .start_transaction = start_smic_transaction, | 590 | .start_transaction = start_smic_transaction, |
594 | .get_result = smic_get_result, | 591 | .get_result = smic_get_result, |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index d35a953961cb..e71aaae855ad 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -53,8 +53,6 @@ | |||
53 | 53 | ||
54 | #define PFX "IPMI Watchdog: " | 54 | #define PFX "IPMI Watchdog: " |
55 | 55 | ||
56 | #define IPMI_WATCHDOG_VERSION "v33" | ||
57 | |||
58 | /* | 56 | /* |
59 | * The IPMI command/response information for the watchdog timer. | 57 | * The IPMI command/response information for the watchdog timer. |
60 | */ | 58 | */ |
@@ -259,7 +257,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, | |||
259 | 257 | ||
260 | data[1] = 0; | 258 | data[1] = 0; |
261 | WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); | 259 | WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); |
262 | if (pretimeout > 0) { | 260 | if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) { |
263 | WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); | 261 | WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); |
264 | data[2] = pretimeout; | 262 | data[2] = pretimeout; |
265 | } else { | 263 | } else { |
@@ -659,19 +657,18 @@ static ssize_t ipmi_read(struct file *file, | |||
659 | 657 | ||
660 | static int ipmi_open(struct inode *ino, struct file *filep) | 658 | static int ipmi_open(struct inode *ino, struct file *filep) |
661 | { | 659 | { |
662 | switch (iminor(ino)) | 660 | switch (iminor(ino)) { |
663 | { | 661 | case WATCHDOG_MINOR: |
664 | case WATCHDOG_MINOR: | 662 | if (test_and_set_bit(0, &ipmi_wdog_open)) |
665 | if(test_and_set_bit(0, &ipmi_wdog_open)) | ||
666 | return -EBUSY; | 663 | return -EBUSY; |
667 | 664 | ||
668 | /* Don't start the timer now, let it start on the | 665 | /* Don't start the timer now, let it start on the |
669 | first heartbeat. */ | 666 | first heartbeat. */ |
670 | ipmi_start_timer_on_heartbeat = 1; | 667 | ipmi_start_timer_on_heartbeat = 1; |
671 | return nonseekable_open(ino, filep); | 668 | return nonseekable_open(ino, filep); |
672 | 669 | ||
673 | default: | 670 | default: |
674 | return (-ENODEV); | 671 | return (-ENODEV); |
675 | } | 672 | } |
676 | } | 673 | } |
677 | 674 | ||
@@ -817,15 +814,19 @@ static void ipmi_register_watchdog(int ipmi_intf) | |||
817 | static int | 814 | static int |
818 | ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) | 815 | ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) |
819 | { | 816 | { |
817 | /* If we are not expecting a timeout, ignore it. */ | ||
818 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) | ||
819 | return NOTIFY_DONE; | ||
820 | |||
820 | /* If no one else handled the NMI, we assume it was the IPMI | 821 | /* If no one else handled the NMI, we assume it was the IPMI |
821 | watchdog. */ | 822 | watchdog. */ |
822 | if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) | 823 | if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { |
824 | /* On some machines, the heartbeat will give | ||
825 | an error and not work unless we re-enable | ||
826 | the timer. So do so. */ | ||
827 | pretimeout_since_last_heartbeat = 1; | ||
823 | panic(PFX "pre-timeout"); | 828 | panic(PFX "pre-timeout"); |
824 | 829 | } | |
825 | /* On some machines, the heartbeat will give | ||
826 | an error and not work unless we re-enable | ||
827 | the timer. So do so. */ | ||
828 | pretimeout_since_last_heartbeat = 1; | ||
829 | 830 | ||
830 | return NOTIFY_DONE; | 831 | return NOTIFY_DONE; |
831 | } | 832 | } |
@@ -924,9 +925,6 @@ static int __init ipmi_wdog_init(void) | |||
924 | { | 925 | { |
925 | int rv; | 926 | int rv; |
926 | 927 | ||
927 | printk(KERN_INFO PFX "driver version " | ||
928 | IPMI_WATCHDOG_VERSION "\n"); | ||
929 | |||
930 | if (strcmp(action, "reset") == 0) { | 928 | if (strcmp(action, "reset") == 0) { |
931 | action_val = WDOG_TIMEOUT_RESET; | 929 | action_val = WDOG_TIMEOUT_RESET; |
932 | } else if (strcmp(action, "none") == 0) { | 930 | } else if (strcmp(action, "none") == 0) { |
@@ -1011,6 +1009,8 @@ static int __init ipmi_wdog_init(void) | |||
1011 | register_reboot_notifier(&wdog_reboot_notifier); | 1009 | register_reboot_notifier(&wdog_reboot_notifier); |
1012 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); | 1010 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); |
1013 | 1011 | ||
1012 | printk(KERN_INFO PFX "driver initialized\n"); | ||
1013 | |||
1014 | return 0; | 1014 | return 0; |
1015 | } | 1015 | } |
1016 | 1016 | ||
@@ -1062,3 +1062,5 @@ static void __exit ipmi_wdog_exit(void) | |||
1062 | module_exit(ipmi_wdog_exit); | 1062 | module_exit(ipmi_wdog_exit); |
1063 | module_init(ipmi_wdog_init); | 1063 | module_init(ipmi_wdog_init); |
1064 | MODULE_LICENSE("GPL"); | 1064 | MODULE_LICENSE("GPL"); |
1065 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
1066 | MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface."); | ||