Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipmi: test for event buffer before using

The IPMI driver would attempt to use the event buffer even if that
didn't exist on the BMC. This patch modified the IPMI driver to check
for the event buffer's existence before trying to use it.

Signed-off-by: Corey Minyard <minyard@acm.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Corey Minyard and committed by
Linus Torvalds
40112ae7 8b32b5d0

+126 -30
+120 -30
drivers/char/ipmi/ipmi_si_intf.c
··· 82 82 #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a 83 83 short timeout */ 84 84 85 - /* Bit for BMC global enables. */ 86 - #define IPMI_BMC_RCV_MSG_INTR 0x01 87 - #define IPMI_BMC_EVT_MSG_INTR 0x02 88 - #define IPMI_BMC_EVT_MSG_BUFF 0x04 89 - #define IPMI_BMC_SYS_LOG 0x08 90 - 91 85 enum si_intf_state { 92 86 SI_NORMAL, 93 87 SI_GETTING_FLAGS, ··· 213 219 OEM1_DATA_AVAIL | \ 214 220 OEM2_DATA_AVAIL) 215 221 unsigned char msg_flags; 222 + 223 + /* Does the BMC have an event buffer? */ 224 + char has_event_buffer; 216 225 217 226 /* 218 227 * If set to true, this will request events the next time the ··· 965 968 { 966 969 struct smi_info *smi_info = send_info; 967 970 968 - if (atomic_read(&smi_info->stop_operation)) 971 + if (atomic_read(&smi_info->stop_operation) || 972 + !smi_info->has_event_buffer) 969 973 return; 970 974 971 975 atomic_set(&smi_info->req_events, 1); ··· 2405 2407 }; 2406 2408 #endif /* CONFIG_PPC_OF */ 2407 2409 2408 - 2409 - static int try_get_dev_id(struct smi_info *smi_info) 2410 + static int wait_for_msg_done(struct smi_info *smi_info) 2410 2411 { 2411 - unsigned char msg[2]; 2412 - unsigned char *resp; 2413 - unsigned long resp_len; 2414 2412 enum si_sm_result smi_result; 2415 - int rv = 0; 2416 - 2417 - resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 2418 - if (!resp) 2419 - return -ENOMEM; 2420 - 2421 - /* 2422 - * Do a Get Device ID command, since it comes back with some 2423 - * useful info. 2424 - */ 2425 - msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2426 - msg[1] = IPMI_GET_DEVICE_ID_CMD; 2427 - smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 2428 2413 2429 2414 smi_result = smi_info->handlers->event(smi_info->si_sm, 0); 2430 2415 for (;;) { ··· 2422 2441 } else 2423 2442 break; 2424 2443 } 2425 - if (smi_result == SI_SM_HOSED) { 2444 + if (smi_result == SI_SM_HOSED) 2426 2445 /* 2427 2446 * We couldn't get the state machine to run, so whatever's at 2428 2447 * the port is probably not an IPMI SMI interface. 2429 2448 */ 2430 - rv = -ENODEV; 2431 - goto out; 2432 - } 2449 + return -ENODEV; 2433 2450 2434 - /* Otherwise, we got some data. */ 2451 + return 0; 2452 + } 2453 + 2454 + static int try_get_dev_id(struct smi_info *smi_info) 2455 + { 2456 + unsigned char msg[2]; 2457 + unsigned char *resp; 2458 + unsigned long resp_len; 2459 + int rv = 0; 2460 + 2461 + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 2462 + if (!resp) 2463 + return -ENOMEM; 2464 + 2465 + /* 2466 + * Do a Get Device ID command, since it comes back with some 2467 + * useful info. 2468 + */ 2469 + msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2470 + msg[1] = IPMI_GET_DEVICE_ID_CMD; 2471 + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 2472 + 2473 + rv = wait_for_msg_done(smi_info); 2474 + if (rv) 2475 + goto out; 2476 + 2435 2477 resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2436 2478 resp, IPMI_MAX_MSG_LENGTH); 2437 2479 2438 2480 /* Check and record info from the get device id, in case we need it. */ 2439 2481 rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id); 2440 2482 2483 + out: 2484 + kfree(resp); 2485 + return rv; 2486 + } 2487 + 2488 + static int try_enable_event_buffer(struct smi_info *smi_info) 2489 + { 2490 + unsigned char msg[3]; 2491 + unsigned char *resp; 2492 + unsigned long resp_len; 2493 + int rv = 0; 2494 + 2495 + resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 2496 + if (!resp) 2497 + return -ENOMEM; 2498 + 2499 + msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2500 + msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; 2501 + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 2502 + 2503 + rv = wait_for_msg_done(smi_info); 2504 + if (rv) { 2505 + printk(KERN_WARNING 2506 + "ipmi_si: Error getting response from get global," 2507 + " enables command, the event buffer is not" 2508 + " enabled.\n"); 2509 + goto out; 2510 + } 2511 + 2512 + resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2513 + resp, IPMI_MAX_MSG_LENGTH); 2514 + 2515 + if (resp_len < 4 || 2516 + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2517 + resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || 2518 + resp[2] != 0) { 2519 + printk(KERN_WARNING 2520 + "ipmi_si: Invalid return from get global" 2521 + " enables command, cannot enable the event" 2522 + " buffer.\n"); 2523 + rv = -EINVAL; 2524 + goto out; 2525 + } 2526 + 2527 + if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) 2528 + /* buffer is already enabled, nothing to do. */ 2529 + goto out; 2530 + 2531 + msg[0] = IPMI_NETFN_APP_REQUEST << 2; 2532 + msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; 2533 + msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF; 2534 + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); 2535 + 2536 + rv = wait_for_msg_done(smi_info); 2537 + if (rv) { 2538 + printk(KERN_WARNING 2539 + "ipmi_si: Error getting response from set global," 2540 + " enables command, the event buffer is not" 2541 + " enabled.\n"); 2542 + goto out; 2543 + } 2544 + 2545 + resp_len = smi_info->handlers->get_result(smi_info->si_sm, 2546 + resp, IPMI_MAX_MSG_LENGTH); 2547 + 2548 + if (resp_len < 3 || 2549 + resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || 2550 + resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { 2551 + printk(KERN_WARNING 2552 + "ipmi_si: Invalid return from get global," 2553 + "enables command, not enable the event" 2554 + " buffer.\n"); 2555 + rv = -EINVAL; 2556 + goto out; 2557 + } 2558 + 2559 + if (resp[2] != 0) 2560 + /* 2561 + * An error when setting the event buffer bit means 2562 + * that the event buffer is not supported. 2563 + */ 2564 + rv = -ENOENT; 2441 2565 out: 2442 2566 kfree(resp); 2443 2567 return rv; ··· 2932 2846 atomic_set(&new_smi->stop_operation, 0); 2933 2847 new_smi->intf_num = smi_num; 2934 2848 smi_num++; 2849 + 2850 + rv = try_enable_event_buffer(new_smi); 2851 + if (rv == 0) 2852 + new_smi->has_event_buffer = 1; 2935 2853 2936 2854 /* 2937 2855 * Start clearing the flags before we enable interrupts or the
+6
include/linux/ipmi_msgdefs.h
··· 58 58 #define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35 59 59 #define IPMI_GET_CHANNEL_INFO_CMD 0x42 60 60 61 + /* Bit for BMC global enables. */ 62 + #define IPMI_BMC_RCV_MSG_INTR 0x01 63 + #define IPMI_BMC_EVT_MSG_INTR 0x02 64 + #define IPMI_BMC_EVT_MSG_BUFF 0x04 65 + #define IPMI_BMC_SYS_LOG 0x08 66 + 61 67 #define IPMI_NETFN_STORAGE_REQUEST 0x0a 62 68 #define IPMI_NETFN_STORAGE_RESPONSE 0x0b 63 69 #define IPMI_ADD_SEL_ENTRY_CMD 0x44