X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fipmi%2Fipmi_msghandler.c;h=fe02300e621c657d1dea06b0d06bd7c336e147e1;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=aa0fe2dbfaf0e01e900ffe240edfc0f2f7bc9ca7;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index aa0fe2dbf..fe02300e6 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -46,9 +46,10 @@ #include #include -#define IPMI_MSGHANDLER_VERSION "v31" +#define PFX "IPMI message handler: " +#define IPMI_MSGHANDLER_VERSION "v33" -struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); +static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); static int initialized = 0; @@ -293,44 +294,6 @@ struct ipmi_smi unsigned int events; }; -int -ipmi_register_all_cmd_rcvr(ipmi_user_t user) -{ - unsigned long flags; - int rv = -EBUSY; - - write_lock_irqsave(&(user->intf->users_lock), flags); - write_lock(&(user->intf->cmd_rcvr_lock)); - if ((user->intf->all_cmd_rcvr == NULL) - && (list_empty(&(user->intf->cmd_rcvrs)))) - { - user->intf->all_cmd_rcvr = user; - rv = 0; - } - write_unlock(&(user->intf->cmd_rcvr_lock)); - write_unlock_irqrestore(&(user->intf->users_lock), flags); - return rv; -} - -int -ipmi_unregister_all_cmd_rcvr(ipmi_user_t user) -{ - unsigned long flags; - int rv = -EINVAL; - - write_lock_irqsave(&(user->intf->users_lock), flags); - write_lock(&(user->intf->cmd_rcvr_lock)); - if (user->intf->all_cmd_rcvr == user) - { - user->intf->all_cmd_rcvr = NULL; - rv = 0; - } - write_unlock(&(user->intf->cmd_rcvr_lock)); - write_unlock_irqrestore(&(user->intf->users_lock), flags); - return rv; -} - - #define MAX_IPMI_INTERFACES 4 static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; @@ -341,7 +304,7 @@ static DECLARE_RWSEM(interfaces_sem); /* Directly protects the ipmi_interfaces data structure. This is claimed in the timer interrupt. */ -static spinlock_t interfaces_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(interfaces_lock); /* List of watchers that want to know when smi's are added and deleted. */ @@ -388,7 +351,7 @@ call_smi_watchers(int i) up_read(&smi_watchers_sem); } -int +static int ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2) { if (addr1->addr_type != addr2->addr_type) @@ -480,6 +443,9 @@ unsigned int ipmi_addr_length(int addr_type) return sizeof(struct ipmi_ipmb_addr); } + if (addr_type == IPMI_LAN_ADDR_TYPE) + return sizeof(struct ipmi_lan_addr); + return 0; } @@ -895,6 +861,12 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, return rv; } +void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) +{ + user->intf->handlers->set_run_to_completion(user->intf->send_info, + val); +} + static unsigned char ipmb_checksum(unsigned char *data, int size) { @@ -907,7 +879,7 @@ ipmb_checksum(unsigned char *data, int size) } static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg, - struct ipmi_msg *msg, + struct kernel_ipmi_msg *msg, struct ipmi_ipmb_addr *ipmb_addr, long msgid, unsigned char ipmb_seq, @@ -949,7 +921,7 @@ static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg, } static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, - struct ipmi_msg *msg, + struct kernel_ipmi_msg *msg, struct ipmi_lan_addr *lan_addr, long msgid, unsigned char ipmb_seq, @@ -993,7 +965,7 @@ static inline int i_ipmi_request(ipmi_user_t user, ipmi_smi_t intf, struct ipmi_addr *addr, long msgid, - struct ipmi_msg *msg, + struct kernel_ipmi_msg *msg, void *user_msg_data, void *supplied_smi, struct ipmi_recv_msg *supplied_recv, @@ -1335,7 +1307,7 @@ static inline int i_ipmi_request(ipmi_user_t user, goto out_err; } -#if DEBUG_MSGING +#ifdef DEBUG_MSGING { int m; for (m=0; mdata_size; m++) @@ -1353,30 +1325,10 @@ static inline int i_ipmi_request(ipmi_user_t user, return rv; } -int ipmi_request(ipmi_user_t user, - struct ipmi_addr *addr, - long msgid, - struct ipmi_msg *msg, - void *user_msg_data, - int priority) -{ - return i_ipmi_request(user, - user->intf, - addr, - msgid, - msg, - user_msg_data, - NULL, NULL, - priority, - user->intf->my_address, - user->intf->my_lun, - -1, 0); -} - int ipmi_request_settime(ipmi_user_t user, struct ipmi_addr *addr, long msgid, - struct ipmi_msg *msg, + struct kernel_ipmi_msg *msg, void *user_msg_data, int priority, int retries, @@ -1399,7 +1351,7 @@ int ipmi_request_settime(ipmi_user_t user, int ipmi_request_supply_msgs(ipmi_user_t user, struct ipmi_addr *addr, long msgid, - struct ipmi_msg *msg, + struct kernel_ipmi_msg *msg, void *user_msg_data, void *supplied_smi, struct ipmi_recv_msg *supplied_recv, @@ -1419,28 +1371,6 @@ int ipmi_request_supply_msgs(ipmi_user_t user, -1, 0); } -int ipmi_request_with_source(ipmi_user_t user, - struct ipmi_addr *addr, - long msgid, - struct ipmi_msg *msg, - void *user_msg_data, - int priority, - unsigned char source_address, - unsigned char source_lun) -{ - return i_ipmi_request(user, - user->intf, - addr, - msgid, - msg, - user_msg_data, - NULL, NULL, - priority, - source_address, - source_lun, - -1, 0); -} - static int ipmb_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1609,7 +1539,7 @@ static void remove_proc_entries(ipmi_smi_t smi) static int send_channel_info_cmd(ipmi_smi_t intf, int chan) { - struct ipmi_msg msg; + struct kernel_ipmi_msg msg; unsigned char data[1]; struct ipmi_system_interface_addr si; @@ -1648,6 +1578,22 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) /* It's the one we want */ if (msg->rsp[2] != 0) { /* Got an error from the channel, just go on. */ + + if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { + /* If the MC does not support this + command, that is legal. We just + assume it has one IPMB at channel + zero. */ + intf->channels[0].medium + = IPMI_CHANNEL_MEDIUM_IPMB; + intf->channels[0].protocol + = IPMI_CHANNEL_PROTOCOL_IPMB; + rv = -ENOSYS; + + intf->curr_channel = IPMI_MAX_CHANNELS; + wake_up(&intf->waitq); + goto out; + } goto next_channel; } if (msg->rsp_size < 6) { @@ -1670,11 +1616,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) intf->curr_channel = IPMI_MAX_CHANNELS; wake_up(&intf->waitq); - printk(KERN_WARNING "ipmi_msghandler: Error sending" - "channel information: 0x%x\n", + printk(KERN_WARNING PFX + "Error sending channel information: %d\n", rv); } } + out: + return; } int ipmi_register_smi(struct ipmi_smi_handlers *handlers, @@ -2007,7 +1955,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, msg->data[10] = ipmb_checksum(&(msg->data[6]), 4); msg->data_size = 11; -#if DEBUG_MSGING +#ifdef DEBUG_MSGING { int m; printk("Invalid command:"); @@ -2325,7 +2273,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, } else { /* There's too many things in the queue, discard this message. */ - printk(KERN_WARNING "ipmi: Event queue full, discarding an" + printk(KERN_WARNING PFX "Event queue full, discarding an" " incoming event\n"); } @@ -2356,12 +2304,17 @@ static int handle_bmc_rsp(ipmi_smi_t intf, if (!found) { /* Special handling for NULL users. */ - if (!recv_msg->user && intf->null_user_handler) + if (!recv_msg->user && intf->null_user_handler){ intf->null_user_handler(intf, msg); - /* The user for the message went away, so give up. */ - spin_lock_irqsave(&intf->counter_lock, flags); - intf->unhandled_local_responses++; - spin_unlock_irqrestore(&intf->counter_lock, flags); + spin_lock_irqsave(&intf->counter_lock, flags); + intf->handled_local_responses++; + spin_unlock_irqrestore(&intf->counter_lock, flags); + }else{ + /* The user for the message went away, so give up. */ + spin_lock_irqsave(&intf->counter_lock, flags); + intf->unhandled_local_responses++; + spin_unlock_irqrestore(&intf->counter_lock, flags); + } ipmi_free_recv_msg(recv_msg); } else { struct ipmi_system_interface_addr *smi_addr; @@ -2398,7 +2351,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, int requeue; int chan; -#if DEBUG_MSGING +#ifdef DEBUG_MSGING int m; printk("Recv:"); for (m=0; mrsp_size; m++) @@ -2407,10 +2360,34 @@ static int handle_new_recv_msg(ipmi_smi_t intf, #endif if (msg->rsp_size < 2) { /* Message is too small to be correct. */ - requeue = 0; - } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) - && (msg->rsp[1] == IPMI_SEND_MSG_CMD) - && (msg->user_data != NULL)) + printk(KERN_WARNING PFX "BMC returned to small a message" + " for netfn %x cmd %x, got %d bytes\n", + (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size); + + /* Generate an error response for the message. */ + msg->rsp[0] = msg->data[0] | (1 << 2); + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = IPMI_ERR_UNSPECIFIED; + msg->rsp_size = 3; + } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */ + || (msg->rsp[1] != msg->data[1])) /* Command */ + { + /* The response is not even marginally correct. */ + printk(KERN_WARNING PFX "BMC returned incorrect response," + " expected netfn %x cmd %x, got netfn %x cmd %x\n", + (msg->data[0] >> 2) | 1, msg->data[1], + msg->rsp[0] >> 2, msg->rsp[1]); + + /* Generate an error response for the message. */ + msg->rsp[0] = msg->data[0] | (1 << 2); + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = IPMI_ERR_UNSPECIFIED; + msg->rsp_size = 3; + } + + if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) + && (msg->rsp[1] == IPMI_SEND_MSG_CMD) + && (msg->user_data != NULL)) { /* It's a response to a response we sent. For this we deliver a send message response to the user. */ @@ -2476,7 +2453,9 @@ static int handle_new_recv_msg(ipmi_smi_t intf, requeue = 0; } - } else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) { + } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) + && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) + { /* It's an asyncronous event. */ requeue = handle_read_event_rsp(intf, msg); } else { @@ -2613,7 +2592,7 @@ send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, MC, which don't get resent. */ intf->handlers->sender(intf->send_info, smi_msg, 0); -#if DEBUG_MSGING +#ifdef DEBUG_MSGING { int m; printk("Resend: "); @@ -2847,7 +2826,7 @@ static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) static void send_panic_events(char *str) { - struct ipmi_msg msg; + struct kernel_ipmi_msg msg; ipmi_smi_t intf; unsigned char data[16]; int i; @@ -3067,12 +3046,12 @@ static int panic_event(struct notifier_block *this, } static struct notifier_block panic_block = { - panic_event, - NULL, - 200 /* priority: INT_MAX >= x >= 0 */ + .notifier_call = panic_event, + .next = NULL, + .priority = 200 /* priority: INT_MAX >= x >= 0 */ }; -static __init int ipmi_init_msghandler(void) +static int ipmi_init_msghandler(void) { int i; @@ -3086,9 +3065,9 @@ static __init int ipmi_init_msghandler(void) ipmi_interfaces[i] = NULL; } - proc_ipmi_root = proc_mkdir("ipmi", 0); + proc_ipmi_root = proc_mkdir("ipmi", NULL); if (!proc_ipmi_root) { - printk("Unable to create IPMI proc dir"); + printk(KERN_ERR PFX "Unable to create IPMI proc dir"); return -ENOMEM; } @@ -3107,6 +3086,12 @@ static __init int ipmi_init_msghandler(void) return 0; } +static __init int ipmi_init_msghandler_mod(void) +{ + ipmi_init_msghandler(); + return 0; +} + static __exit void cleanup_ipmi(void) { int count; @@ -3134,26 +3119,23 @@ static __exit void cleanup_ipmi(void) /* Check for buffer leaks. */ count = atomic_read(&smi_msg_inuse_count); if (count != 0) - printk("ipmi_msghandler: SMI message count %d at exit\n", + printk(KERN_WARNING PFX "SMI message count %d at exit\n", count); count = atomic_read(&recv_msg_inuse_count); if (count != 0) - printk("ipmi_msghandler: recv message count %d at exit\n", + printk(KERN_WARNING PFX "recv message count %d at exit\n", count); } module_exit(cleanup_ipmi); -module_init(ipmi_init_msghandler); +module_init(ipmi_init_msghandler_mod); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(ipmi_alloc_recv_msg); EXPORT_SYMBOL(ipmi_create_user); EXPORT_SYMBOL(ipmi_destroy_user); EXPORT_SYMBOL(ipmi_get_version); -EXPORT_SYMBOL(ipmi_request); EXPORT_SYMBOL(ipmi_request_settime); EXPORT_SYMBOL(ipmi_request_supply_msgs); -EXPORT_SYMBOL(ipmi_request_with_source); EXPORT_SYMBOL(ipmi_register_smi); EXPORT_SYMBOL(ipmi_unregister_smi); EXPORT_SYMBOL(ipmi_register_for_cmd); @@ -3161,12 +3143,9 @@ EXPORT_SYMBOL(ipmi_unregister_for_cmd); EXPORT_SYMBOL(ipmi_smi_msg_received); EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout); EXPORT_SYMBOL(ipmi_alloc_smi_msg); -EXPORT_SYMBOL(ipmi_register_all_cmd_rcvr); -EXPORT_SYMBOL(ipmi_unregister_all_cmd_rcvr); EXPORT_SYMBOL(ipmi_addr_length); EXPORT_SYMBOL(ipmi_validate_addr); EXPORT_SYMBOL(ipmi_set_gets_events); -EXPORT_SYMBOL(ipmi_addr_equal); EXPORT_SYMBOL(ipmi_smi_watcher_register); EXPORT_SYMBOL(ipmi_smi_watcher_unregister); EXPORT_SYMBOL(ipmi_set_my_address); @@ -3174,3 +3153,4 @@ EXPORT_SYMBOL(ipmi_get_my_address); EXPORT_SYMBOL(ipmi_set_my_LUN); EXPORT_SYMBOL(ipmi_get_my_LUN); EXPORT_SYMBOL(ipmi_smi_add_proc_entry); +EXPORT_SYMBOL(ipmi_user_set_run_to_completion);