|
@@ -124,6 +124,14 @@ struct ipmi_channel
|
|
|
{
|
|
|
unsigned char medium;
|
|
|
unsigned char protocol;
|
|
|
+
|
|
|
+ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
|
|
|
+ but may be changed by the user. */
|
|
|
+ unsigned char address;
|
|
|
+
|
|
|
+ /* My LUN. This should generally stay the SMS LUN, but just in
|
|
|
+ case... */
|
|
|
+ unsigned char lun;
|
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
@@ -135,7 +143,7 @@ struct ipmi_proc_entry
|
|
|
#endif
|
|
|
|
|
|
#define IPMI_IPMB_NUM_SEQ 64
|
|
|
-#define IPMI_MAX_CHANNELS 8
|
|
|
+#define IPMI_MAX_CHANNELS 16
|
|
|
struct ipmi_smi
|
|
|
{
|
|
|
/* What interface number are we? */
|
|
@@ -199,14 +207,6 @@ struct ipmi_smi
|
|
|
this is registered. */
|
|
|
ipmi_user_t all_cmd_rcvr;
|
|
|
|
|
|
- /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
|
|
|
- but may be changed by the user. */
|
|
|
- unsigned char my_address;
|
|
|
-
|
|
|
- /* My LUN. This should generally stay the SMS LUN, but just in
|
|
|
- case... */
|
|
|
- unsigned char my_lun;
|
|
|
-
|
|
|
/* The event receiver for my BMC, only really used at panic
|
|
|
shutdown as a place to store this. */
|
|
|
unsigned char event_receiver;
|
|
@@ -766,26 +766,44 @@ void ipmi_get_version(ipmi_user_t user,
|
|
|
*minor = user->intf->version_minor;
|
|
|
}
|
|
|
|
|
|
-void ipmi_set_my_address(ipmi_user_t user,
|
|
|
- unsigned char address)
|
|
|
+int ipmi_set_my_address(ipmi_user_t user,
|
|
|
+ unsigned int channel,
|
|
|
+ unsigned char address)
|
|
|
{
|
|
|
- user->intf->my_address = address;
|
|
|
+ if (channel >= IPMI_MAX_CHANNELS)
|
|
|
+ return -EINVAL;
|
|
|
+ user->intf->channels[channel].address = address;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-unsigned char ipmi_get_my_address(ipmi_user_t user)
|
|
|
+int ipmi_get_my_address(ipmi_user_t user,
|
|
|
+ unsigned int channel,
|
|
|
+ unsigned char *address)
|
|
|
{
|
|
|
- return user->intf->my_address;
|
|
|
+ if (channel >= IPMI_MAX_CHANNELS)
|
|
|
+ return -EINVAL;
|
|
|
+ *address = user->intf->channels[channel].address;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-void ipmi_set_my_LUN(ipmi_user_t user,
|
|
|
- unsigned char LUN)
|
|
|
+int ipmi_set_my_LUN(ipmi_user_t user,
|
|
|
+ unsigned int channel,
|
|
|
+ unsigned char LUN)
|
|
|
{
|
|
|
- user->intf->my_lun = LUN & 0x3;
|
|
|
+ if (channel >= IPMI_MAX_CHANNELS)
|
|
|
+ return -EINVAL;
|
|
|
+ user->intf->channels[channel].lun = LUN & 0x3;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-unsigned char ipmi_get_my_LUN(ipmi_user_t user)
|
|
|
+int ipmi_get_my_LUN(ipmi_user_t user,
|
|
|
+ unsigned int channel,
|
|
|
+ unsigned char *address)
|
|
|
{
|
|
|
- return user->intf->my_lun;
|
|
|
+ if (channel >= IPMI_MAX_CHANNELS)
|
|
|
+ return -EINVAL;
|
|
|
+ *address = user->intf->channels[channel].lun;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int ipmi_set_gets_events(ipmi_user_t user, int val)
|
|
@@ -1213,7 +1231,7 @@ static inline int i_ipmi_request(ipmi_user_t user,
|
|
|
unsigned char ipmb_seq;
|
|
|
long seqid;
|
|
|
|
|
|
- if (addr->channel > IPMI_NUM_CHANNELS) {
|
|
|
+ if (addr->channel >= IPMI_NUM_CHANNELS) {
|
|
|
spin_lock_irqsave(&intf->counter_lock, flags);
|
|
|
intf->sent_invalid_commands++;
|
|
|
spin_unlock_irqrestore(&intf->counter_lock, flags);
|
|
@@ -1346,6 +1364,18 @@ static inline int i_ipmi_request(ipmi_user_t user,
|
|
|
return rv;
|
|
|
}
|
|
|
|
|
|
+static int check_addr(ipmi_smi_t intf,
|
|
|
+ struct ipmi_addr *addr,
|
|
|
+ unsigned char *saddr,
|
|
|
+ unsigned char *lun)
|
|
|
+{
|
|
|
+ if (addr->channel >= IPMI_MAX_CHANNELS)
|
|
|
+ return -EINVAL;
|
|
|
+ *lun = intf->channels[addr->channel].lun;
|
|
|
+ *saddr = intf->channels[addr->channel].address;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int ipmi_request_settime(ipmi_user_t user,
|
|
|
struct ipmi_addr *addr,
|
|
|
long msgid,
|
|
@@ -1355,6 +1385,12 @@ int ipmi_request_settime(ipmi_user_t user,
|
|
|
int retries,
|
|
|
unsigned int retry_time_ms)
|
|
|
{
|
|
|
+ unsigned char saddr, lun;
|
|
|
+ int rv;
|
|
|
+
|
|
|
+ rv = check_addr(user->intf, addr, &saddr, &lun);
|
|
|
+ if (rv)
|
|
|
+ return rv;
|
|
|
return i_ipmi_request(user,
|
|
|
user->intf,
|
|
|
addr,
|
|
@@ -1363,8 +1399,8 @@ int ipmi_request_settime(ipmi_user_t user,
|
|
|
user_msg_data,
|
|
|
NULL, NULL,
|
|
|
priority,
|
|
|
- user->intf->my_address,
|
|
|
- user->intf->my_lun,
|
|
|
+ saddr,
|
|
|
+ lun,
|
|
|
retries,
|
|
|
retry_time_ms);
|
|
|
}
|
|
@@ -1378,6 +1414,12 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
|
|
|
struct ipmi_recv_msg *supplied_recv,
|
|
|
int priority)
|
|
|
{
|
|
|
+ unsigned char saddr, lun;
|
|
|
+ int rv;
|
|
|
+
|
|
|
+ rv = check_addr(user->intf, addr, &saddr, &lun);
|
|
|
+ if (rv)
|
|
|
+ return rv;
|
|
|
return i_ipmi_request(user,
|
|
|
user->intf,
|
|
|
addr,
|
|
@@ -1387,8 +1429,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
|
|
|
supplied_smi,
|
|
|
supplied_recv,
|
|
|
priority,
|
|
|
- user->intf->my_address,
|
|
|
- user->intf->my_lun,
|
|
|
+ saddr,
|
|
|
+ lun,
|
|
|
-1, 0);
|
|
|
}
|
|
|
|
|
@@ -1397,8 +1439,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off,
|
|
|
{
|
|
|
char *out = (char *) page;
|
|
|
ipmi_smi_t intf = data;
|
|
|
+ int i;
|
|
|
+ int rv= 0;
|
|
|
|
|
|
- return sprintf(out, "%x\n", intf->my_address);
|
|
|
+ for (i=0; i<IPMI_MAX_CHANNELS; i++)
|
|
|
+ rv += sprintf(out+rv, "%x ", intf->channels[i].address);
|
|
|
+ out[rv-1] = '\n'; /* Replace the final space with a newline */
|
|
|
+ out[rv] = '\0';
|
|
|
+ rv++;
|
|
|
+ return rv;
|
|
|
}
|
|
|
|
|
|
static int version_file_read_proc(char *page, char **start, off_t off,
|
|
@@ -1592,8 +1641,8 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan)
|
|
|
NULL,
|
|
|
NULL,
|
|
|
0,
|
|
|
- intf->my_address,
|
|
|
- intf->my_lun,
|
|
|
+ intf->channels[0].address,
|
|
|
+ intf->channels[0].lun,
|
|
|
-1, 0);
|
|
|
}
|
|
|
|
|
@@ -1696,11 +1745,13 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
|
|
|
new_intf->intf_num = i;
|
|
|
new_intf->version_major = version_major;
|
|
|
new_intf->version_minor = version_minor;
|
|
|
- if (slave_addr == 0)
|
|
|
- new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
|
|
|
- else
|
|
|
- new_intf->my_address = slave_addr;
|
|
|
- new_intf->my_lun = 2; /* the SMS LUN. */
|
|
|
+ for (j=0; j<IPMI_MAX_CHANNELS; j++) {
|
|
|
+ new_intf->channels[j].address
|
|
|
+ = IPMI_BMC_SLAVE_ADDR;
|
|
|
+ new_intf->channels[j].lun = 2;
|
|
|
+ }
|
|
|
+ if (slave_addr != 0)
|
|
|
+ new_intf->channels[0].address = slave_addr;
|
|
|
rwlock_init(&(new_intf->users_lock));
|
|
|
INIT_LIST_HEAD(&(new_intf->users));
|
|
|
new_intf->handlers = handlers;
|
|
@@ -1985,7 +2036,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
|
|
|
msg->data[3] = msg->rsp[6];
|
|
|
msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
|
|
|
msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
|
|
|
- msg->data[6] = intf->my_address;
|
|
|
+ msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
|
|
|
/* rqseq/lun */
|
|
|
msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
|
|
|
msg->data[8] = msg->rsp[8]; /* cmd */
|
|
@@ -2919,8 +2970,8 @@ static void send_panic_events(char *str)
|
|
|
&smi_msg,
|
|
|
&recv_msg,
|
|
|
0,
|
|
|
- intf->my_address,
|
|
|
- intf->my_lun,
|
|
|
+ intf->channels[0].address,
|
|
|
+ intf->channels[0].lun,
|
|
|
0, 1); /* Don't retry, and don't wait. */
|
|
|
}
|
|
|
|
|
@@ -2965,8 +3016,8 @@ static void send_panic_events(char *str)
|
|
|
&smi_msg,
|
|
|
&recv_msg,
|
|
|
0,
|
|
|
- intf->my_address,
|
|
|
- intf->my_lun,
|
|
|
+ intf->channels[0].address,
|
|
|
+ intf->channels[0].lun,
|
|
|
0, 1); /* Don't retry, and don't wait. */
|
|
|
|
|
|
if (intf->local_event_generator) {
|
|
@@ -2985,8 +3036,8 @@ static void send_panic_events(char *str)
|
|
|
&smi_msg,
|
|
|
&recv_msg,
|
|
|
0,
|
|
|
- intf->my_address,
|
|
|
- intf->my_lun,
|
|
|
+ intf->channels[0].address,
|
|
|
+ intf->channels[0].lun,
|
|
|
0, 1); /* no retry, and no wait. */
|
|
|
}
|
|
|
intf->null_user_handler = NULL;
|
|
@@ -2996,7 +3047,7 @@ static void send_panic_events(char *str)
|
|
|
be zero, and it must not be my address. */
|
|
|
if (((intf->event_receiver & 1) == 0)
|
|
|
&& (intf->event_receiver != 0)
|
|
|
- && (intf->event_receiver != intf->my_address))
|
|
|
+ && (intf->event_receiver != intf->channels[0].address))
|
|
|
{
|
|
|
/* The event receiver is valid, send an IPMB
|
|
|
message. */
|
|
@@ -3031,7 +3082,7 @@ static void send_panic_events(char *str)
|
|
|
data[0] = 0;
|
|
|
data[1] = 0;
|
|
|
data[2] = 0xf0; /* OEM event without timestamp. */
|
|
|
- data[3] = intf->my_address;
|
|
|
+ data[3] = intf->channels[0].address;
|
|
|
data[4] = j++; /* sequence # */
|
|
|
/* Always give 11 bytes, so strncpy will fill
|
|
|
it with zeroes for me. */
|
|
@@ -3047,8 +3098,8 @@ static void send_panic_events(char *str)
|
|
|
&smi_msg,
|
|
|
&recv_msg,
|
|
|
0,
|
|
|
- intf->my_address,
|
|
|
- intf->my_lun,
|
|
|
+ intf->channels[0].address,
|
|
|
+ intf->channels[0].lun,
|
|
|
0, 1); /* no retry, and no wait. */
|
|
|
}
|
|
|
}
|