Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 143795
b: refs/heads/master
c: 40112ae
h: refs/heads/master
i:
  143793: 5d2ffbd
  143791: 1b22d07
v: v3
  • Loading branch information
Corey Minyard authored and Linus Torvalds committed Apr 21, 2009
1 parent 958b121 commit 0264348
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8b32b5d0dca2f5ab632e8bedcd57fe4c109c13fe
refs/heads/master: 40112ae7504745799e75ef418057f0d2cb745050
148 changes: 119 additions & 29 deletions trunk/drivers/char/ipmi/ipmi_si_intf.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@
#define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a
short timeout */

/* Bit for BMC global enables. */
#define IPMI_BMC_RCV_MSG_INTR 0x01
#define IPMI_BMC_EVT_MSG_INTR 0x02
#define IPMI_BMC_EVT_MSG_BUFF 0x04
#define IPMI_BMC_SYS_LOG 0x08

enum si_intf_state {
SI_NORMAL,
SI_GETTING_FLAGS,
Expand Down Expand Up @@ -220,6 +214,9 @@ struct smi_info {
OEM2_DATA_AVAIL)
unsigned char msg_flags;

/* Does the BMC have an event buffer? */
char has_event_buffer;

/*
* If set to true, this will request events the next time the
* state machine is idle.
Expand Down Expand Up @@ -968,7 +965,8 @@ static void request_events(void *send_info)
{
struct smi_info *smi_info = send_info;

if (atomic_read(&smi_info->stop_operation))
if (atomic_read(&smi_info->stop_operation) ||
!smi_info->has_event_buffer)
return;

atomic_set(&smi_info->req_events, 1);
Expand Down Expand Up @@ -2407,26 +2405,9 @@ static struct of_platform_driver ipmi_of_platform_driver = {
};
#endif /* CONFIG_PPC_OF */


static int try_get_dev_id(struct smi_info *smi_info)
static int wait_for_msg_done(struct smi_info *smi_info)
{
unsigned char msg[2];
unsigned char *resp;
unsigned long resp_len;
enum si_sm_result smi_result;
int rv = 0;

resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
if (!resp)
return -ENOMEM;

/*
* Do a Get Device ID command, since it comes back with some
* useful info.
*/
msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_GET_DEVICE_ID_CMD;
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);

smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
for (;;) {
Expand All @@ -2441,16 +2422,39 @@ static int try_get_dev_id(struct smi_info *smi_info)
} else
break;
}
if (smi_result == SI_SM_HOSED) {
if (smi_result == SI_SM_HOSED)
/*
* We couldn't get the state machine to run, so whatever's at
* the port is probably not an IPMI SMI interface.
*/
rv = -ENODEV;
return -ENODEV;

return 0;
}

static int try_get_dev_id(struct smi_info *smi_info)
{
unsigned char msg[2];
unsigned char *resp;
unsigned long resp_len;
int rv = 0;

resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
if (!resp)
return -ENOMEM;

/*
* Do a Get Device ID command, since it comes back with some
* useful info.
*/
msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_GET_DEVICE_ID_CMD;
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);

rv = wait_for_msg_done(smi_info);
if (rv)
goto out;
}

/* Otherwise, we got some data. */
resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);

Expand All @@ -2462,6 +2466,88 @@ static int try_get_dev_id(struct smi_info *smi_info)
return rv;
}

static int try_enable_event_buffer(struct smi_info *smi_info)
{
unsigned char msg[3];
unsigned char *resp;
unsigned long resp_len;
int rv = 0;

resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
if (!resp)
return -ENOMEM;

msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);

rv = wait_for_msg_done(smi_info);
if (rv) {
printk(KERN_WARNING
"ipmi_si: Error getting response from get global,"
" enables command, the event buffer is not"
" enabled.\n");
goto out;
}

resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);

if (resp_len < 4 ||
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
resp[2] != 0) {
printk(KERN_WARNING
"ipmi_si: Invalid return from get global"
" enables command, cannot enable the event"
" buffer.\n");
rv = -EINVAL;
goto out;
}

if (resp[3] & IPMI_BMC_EVT_MSG_BUFF)
/* buffer is already enabled, nothing to do. */
goto out;

msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF;
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);

rv = wait_for_msg_done(smi_info);
if (rv) {
printk(KERN_WARNING
"ipmi_si: Error getting response from set global,"
" enables command, the event buffer is not"
" enabled.\n");
goto out;
}

resp_len = smi_info->handlers->get_result(smi_info->si_sm,
resp, IPMI_MAX_MSG_LENGTH);

if (resp_len < 3 ||
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
printk(KERN_WARNING
"ipmi_si: Invalid return from get global,"
"enables command, not enable the event"
" buffer.\n");
rv = -EINVAL;
goto out;
}

if (resp[2] != 0)
/*
* An error when setting the event buffer bit means
* that the event buffer is not supported.
*/
rv = -ENOENT;
out:
kfree(resp);
return rv;
}

static int type_file_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
Expand Down Expand Up @@ -2847,6 +2933,10 @@ static int try_smi_init(struct smi_info *new_smi)
new_smi->intf_num = smi_num;
smi_num++;

rv = try_enable_event_buffer(new_smi);
if (rv == 0)
new_smi->has_event_buffer = 1;

/*
* Start clearing the flags before we enable interrupts or the
* timer to avoid racing with the timer.
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/linux/ipmi_msgdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
#define IPMI_GET_CHANNEL_INFO_CMD 0x42

/* Bit for BMC global enables. */
#define IPMI_BMC_RCV_MSG_INTR 0x01
#define IPMI_BMC_EVT_MSG_INTR 0x02
#define IPMI_BMC_EVT_MSG_BUFF 0x04
#define IPMI_BMC_SYS_LOG 0x08

#define IPMI_NETFN_STORAGE_REQUEST 0x0a
#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
#define IPMI_ADD_SEL_ENTRY_CMD 0x44
Expand Down

0 comments on commit 0264348

Please sign in to comment.