ipmi_msghandler.c
来自「linux 内核源代码」· C语言 代码 · 共 2,407 行 · 第 1/5 页
C
2,407 行
intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; } if (retries < 0) { if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) retries = 0; /* Don't retry broadcasts. */ else retries = 4; } if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) { /* Broadcasts add a zero at the beginning of the message, but otherwise is the same as an IPMB address. */ addr->addr_type = IPMI_IPMB_ADDR_TYPE; broadcast = 1; } /* Default to 1 second retries. */ if (retry_time_ms == 0) retry_time_ms = 1000; /* 9 for the header and 1 for the checksum, plus possibly one for the broadcast. */ if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EMSGSIZE; goto out_err; } ipmb_addr = (struct ipmi_ipmb_addr *) addr; if (ipmb_addr->lun > 3) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; } memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr)); if (recv_msg->msg.netfn & 0x1) { /* It's a response, so use the user's sequence from msgid. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_ipmb_responses++; spin_unlock_irqrestore(&intf->counter_lock, flags); format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid, msgid, broadcast, source_address, source_lun); /* Save the receive message so we can use it to deliver the response. */ smi_msg->user_data = recv_msg; } else { /* It's a command, so get a sequence for it. */ spin_lock_irqsave(&(intf->seq_lock), flags); spin_lock(&intf->counter_lock); intf->sent_ipmb_commands++; spin_unlock(&intf->counter_lock); /* Create a sequence number with a 1 second timeout and 4 retries. */ rv = intf_next_seq(intf, recv_msg, retry_time_ms, retries, broadcast, &ipmb_seq, &seqid); if (rv) { /* We have used up all the sequence numbers, probably, so abort. */ spin_unlock_irqrestore(&(intf->seq_lock), flags); goto out_err; } /* Store the sequence number in the message, so that when the send message response comes back we can start the timer. */ format_ipmb_msg(smi_msg, msg, ipmb_addr, STORE_SEQ_IN_MSGID(ipmb_seq, seqid), ipmb_seq, broadcast, source_address, source_lun); /* Copy the message into the recv message data, so we can retransmit it later if necessary. */ memcpy(recv_msg->msg_data, smi_msg->data, smi_msg->data_size); recv_msg->msg.data = recv_msg->msg_data; recv_msg->msg.data_len = smi_msg->data_size; /* We don't unlock until here, because we need to copy the completed message into the recv_msg before we release the lock. Otherwise, race conditions may bite us. I know that's pretty paranoid, but I prefer to be correct. */ spin_unlock_irqrestore(&(intf->seq_lock), flags); } } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) { struct ipmi_lan_addr *lan_addr; unsigned char ipmb_seq; long seqid; if (addr->channel >= IPMI_MAX_CHANNELS) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; } if ((intf->channels[addr->channel].medium != IPMI_CHANNEL_MEDIUM_8023LAN) && (intf->channels[addr->channel].medium != IPMI_CHANNEL_MEDIUM_ASYNC)) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; } retries = 4; /* Default to 1 second retries. */ if (retry_time_ms == 0) retry_time_ms = 1000; /* 11 for the header and 1 for the checksum. */ if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EMSGSIZE; goto out_err; } lan_addr = (struct ipmi_lan_addr *) addr; if (lan_addr->lun > 3) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; } memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr)); if (recv_msg->msg.netfn & 0x1) { /* It's a response, so use the user's sequence from msgid. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_lan_responses++; spin_unlock_irqrestore(&intf->counter_lock, flags); format_lan_msg(smi_msg, msg, lan_addr, msgid, msgid, source_lun); /* Save the receive message so we can use it to deliver the response. */ smi_msg->user_data = recv_msg; } else { /* It's a command, so get a sequence for it. */ spin_lock_irqsave(&(intf->seq_lock), flags); spin_lock(&intf->counter_lock); intf->sent_lan_commands++; spin_unlock(&intf->counter_lock); /* Create a sequence number with a 1 second timeout and 4 retries. */ rv = intf_next_seq(intf, recv_msg, retry_time_ms, retries, 0, &ipmb_seq, &seqid); if (rv) { /* We have used up all the sequence numbers, probably, so abort. */ spin_unlock_irqrestore(&(intf->seq_lock), flags); goto out_err; } /* Store the sequence number in the message, so that when the send message response comes back we can start the timer. */ format_lan_msg(smi_msg, msg, lan_addr, STORE_SEQ_IN_MSGID(ipmb_seq, seqid), ipmb_seq, source_lun); /* Copy the message into the recv message data, so we can retransmit it later if necessary. */ memcpy(recv_msg->msg_data, smi_msg->data, smi_msg->data_size); recv_msg->msg.data = recv_msg->msg_data; recv_msg->msg.data_len = smi_msg->data_size; /* We don't unlock until here, because we need to copy the completed message into the recv_msg before we release the lock. Otherwise, race conditions may bite us. I know that's pretty paranoid, but I prefer to be correct. */ spin_unlock_irqrestore(&(intf->seq_lock), flags); } } else { /* Unknown address type. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); rv = -EINVAL; goto out_err; }#ifdef DEBUG_MSGING { int m; for (m = 0; m < smi_msg->data_size; m++) printk(" %2.2x", smi_msg->data[m]); printk("\n"); }#endif handlers->sender(intf->send_info, smi_msg, priority); rcu_read_unlock(); return 0; out_err: rcu_read_unlock(); ipmi_free_smi_msg(smi_msg); ipmi_free_recv_msg(recv_msg); 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, struct kernel_ipmi_msg *msg, void *user_msg_data, int priority, int retries, unsigned int retry_time_ms){ unsigned char saddr, lun; int rv; if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) return rv; return i_ipmi_request(user, user->intf, addr, msgid, msg, user_msg_data, NULL, NULL, priority, saddr, lun, retries, retry_time_ms);}int ipmi_request_supply_msgs(ipmi_user_t user, struct ipmi_addr *addr, long msgid, struct kernel_ipmi_msg *msg, void *user_msg_data, void *supplied_smi, struct ipmi_recv_msg *supplied_recv, int priority){ unsigned char saddr, lun; int rv; if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) return rv; return i_ipmi_request(user, user->intf, addr, msgid, msg, user_msg_data, supplied_smi, supplied_recv, priority, saddr, lun, -1, 0);}#ifdef CONFIG_PROC_FSstatic int ipmb_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ char *out = (char *) page; ipmi_smi_t intf = data; int i; int rv = 0; 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, int count, int *eof, void *data){ char *out = (char *) page; ipmi_smi_t intf = data; return sprintf(out, "%d.%d\n", ipmi_version_major(&intf->bmc->id), ipmi_version_minor(&intf->bmc->id));}static int stat_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ char *out = (char *) page; ipmi_smi_t intf = data; out += sprintf(out, "sent_invalid_commands: %d\n", intf->sent_invalid_commands); out += sprintf(out, "sent_local_commands: %d\n", intf->sent_local_commands); out += sprintf(out, "handled_local_responses: %d\n", intf->handled_local_responses); out += sprintf(out, "unhandled_local_responses: %d\n", intf->unhandled_local_responses); out += sprintf(out, "sent_ipmb_commands: %d\n", intf->sent_ipmb_commands); out += sprintf(out, "sent_ipmb_command_errs: %d\n", intf->sent_ipmb_command_errs); out += sprintf(out, "retransmitted_ipmb_commands: %d\n", intf->retransmitted_ipmb_commands); out += sprintf(out, "timed_out_ipmb_commands: %d\n", intf->timed_out_ipmb_commands); out += sprintf(out, "timed_out_ipmb_broadcasts: %d\n", intf->timed_out_ipmb_broadcasts); out += sprintf(out, "sent_ipmb_responses: %d\n", intf->sent_ipmb_responses); out += sprintf(out, "handled_ipmb_responses: %d\n", intf->handled_ipmb_responses); out += sprintf(out, "invalid_ipmb_responses: %d\n", intf->invalid_ipmb_responses); out += sprintf(out, "unhandled_ipmb_responses: %d\n", intf->unhandled_ipmb_responses); out += sprintf(out, "sent_lan_commands: %d\n", intf->sent_lan_commands); out += sprintf(out, "sent_lan_command_errs: %d\n", intf->sent_lan_command_errs); out += sprintf(out, "retransmitted_lan_commands: %d\n", intf->retransmitted_lan_commands); out += sprintf(out, "timed_out_lan_commands: %d\n", intf->timed_out_lan_commands); out += sprintf(out, "sent_lan_responses: %d\n", intf->sent_lan_responses); out += sprintf(out, "handled_lan_responses: %d\n", intf->handled_lan_responses); out += sprintf(out, "invalid_lan_responses: %d\n", intf->invalid_lan_responses); out += sprintf(out, "unhandled_lan_responses: %d\n", intf->unhandled_lan_responses); out += sprintf(out, "handled_commands: %d\n", intf->handled_commands); out += sprintf(out, "invalid_commands: %d\n", intf->invalid_commands); out += sprintf(out, "unhandled_commands: %d\n", intf->unhandled_commands); out += sprintf(out, "invalid_events: %d\n", intf->invalid_events); out += sprintf(out, "events: %d\n", intf->events); return (out - ((char *) page));}#endif /* CONFIG_PROC_FS */int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, read_proc_t *read_proc, write_proc_t *write_proc, void *data, struct module *owner){ int rv = 0;#ifdef CONFIG_PROC_FS struct proc_dir_entry *file; struct ipmi_proc_entry *entry; /* Create a list element. */ entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; entry->name = kmalloc(strlen(name)+1, GFP_KERNEL); if (!entry->name) { kfree(entry); return -ENOMEM; } strcpy(entry->name, name); file = create_proc_entry(name, 0, smi->proc_dir); if (!file) { kfree(entry->name); kfree(entry); rv = -ENOMEM; } else { file->data = data; file->read_proc = read_proc; file->write_proc = write_proc; file->owner = owner; mutex_lock(&smi->proc_entry_lock); /* Stick it on the list. */ entry->next = smi->proc_entries; smi->proc_entries = entry; mutex_unlock(&smi->proc_entry_lock); }#endif /* CONFIG_PROC_FS */ return rv;}static int add_proc_entries(ipmi_smi_t smi, int num){ int rv = 0;#ifdef CONFIG_PROC_FS sprintf(smi->proc_dir_name, "%d", num); smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); if (!smi->proc_dir) rv = -ENOMEM; else { smi->proc_dir->owner = THIS_MODULE; } if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "stats", stat_file_read_proc, NULL, smi, THIS_MODULE); if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "ipmb", ipmb_file_read_proc, NULL, smi, THIS_MODULE); if (rv == 0) rv = ipmi_smi_add_proc_entry(smi, "version", version_file_read_proc, NULL,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?