| .. | .. |
|---|
| 11 | 11 | * Copyright 2002 MontaVista Software Inc. |
|---|
| 12 | 12 | */ |
|---|
| 13 | 13 | |
|---|
| 14 | +#define pr_fmt(fmt) "IPMI message handler: " fmt |
|---|
| 15 | +#define dev_fmt(fmt) pr_fmt(fmt) |
|---|
| 16 | + |
|---|
| 14 | 17 | #include <linux/module.h> |
|---|
| 15 | 18 | #include <linux/errno.h> |
|---|
| 16 | 19 | #include <linux/poll.h> |
|---|
| .. | .. |
|---|
| 31 | 34 | #include <linux/uuid.h> |
|---|
| 32 | 35 | #include <linux/nospec.h> |
|---|
| 33 | 36 | #include <linux/vmalloc.h> |
|---|
| 34 | | - |
|---|
| 35 | | -#define PFX "IPMI message handler: " |
|---|
| 37 | +#include <linux/delay.h> |
|---|
| 36 | 38 | |
|---|
| 37 | 39 | #define IPMI_DRIVER_VERSION "39.2" |
|---|
| 38 | 40 | |
|---|
| 39 | 41 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
|---|
| 40 | 42 | static int ipmi_init_msghandler(void); |
|---|
| 41 | | -static void smi_recv_tasklet(unsigned long); |
|---|
| 43 | +static void smi_recv_tasklet(struct tasklet_struct *t); |
|---|
| 42 | 44 | static void handle_new_recv_msgs(struct ipmi_smi *intf); |
|---|
| 43 | 45 | static void need_waiter(struct ipmi_smi *intf); |
|---|
| 44 | 46 | static int handle_one_recv_msg(struct ipmi_smi *intf, |
|---|
| 45 | 47 | struct ipmi_smi_msg *msg); |
|---|
| 46 | | - |
|---|
| 47 | | -#ifdef DEBUG |
|---|
| 48 | | -static void ipmi_debug_msg(const char *title, unsigned char *data, |
|---|
| 49 | | - unsigned int len) |
|---|
| 50 | | -{ |
|---|
| 51 | | - int i, pos; |
|---|
| 52 | | - char buf[100]; |
|---|
| 53 | | - |
|---|
| 54 | | - pos = snprintf(buf, sizeof(buf), "%s: ", title); |
|---|
| 55 | | - for (i = 0; i < len; i++) |
|---|
| 56 | | - pos += snprintf(buf + pos, sizeof(buf) - pos, |
|---|
| 57 | | - " %2.2x", data[i]); |
|---|
| 58 | | - pr_debug("%s\n", buf); |
|---|
| 59 | | -} |
|---|
| 60 | | -#else |
|---|
| 61 | | -static void ipmi_debug_msg(const char *title, unsigned char *data, |
|---|
| 62 | | - unsigned int len) |
|---|
| 63 | | -{ } |
|---|
| 64 | | -#endif |
|---|
| 65 | 48 | |
|---|
| 66 | 49 | static bool initialized; |
|---|
| 67 | 50 | static bool drvregistered; |
|---|
| .. | .. |
|---|
| 78 | 61 | #else |
|---|
| 79 | 62 | #define IPMI_PANIC_DEFAULT IPMI_SEND_PANIC_EVENT_NONE |
|---|
| 80 | 63 | #endif |
|---|
| 64 | + |
|---|
| 81 | 65 | static enum ipmi_panic_event_op ipmi_send_panic_event = IPMI_PANIC_DEFAULT; |
|---|
| 82 | 66 | |
|---|
| 83 | 67 | static int panic_op_write_handler(const char *val, |
|---|
| .. | .. |
|---|
| 107 | 91 | { |
|---|
| 108 | 92 | switch (ipmi_send_panic_event) { |
|---|
| 109 | 93 | case IPMI_SEND_PANIC_EVENT_NONE: |
|---|
| 110 | | - strcpy(buffer, "none"); |
|---|
| 94 | + strcpy(buffer, "none\n"); |
|---|
| 111 | 95 | break; |
|---|
| 112 | 96 | |
|---|
| 113 | 97 | case IPMI_SEND_PANIC_EVENT: |
|---|
| 114 | | - strcpy(buffer, "event"); |
|---|
| 98 | + strcpy(buffer, "event\n"); |
|---|
| 115 | 99 | break; |
|---|
| 116 | 100 | |
|---|
| 117 | 101 | case IPMI_SEND_PANIC_EVENT_STRING: |
|---|
| 118 | | - strcpy(buffer, "string"); |
|---|
| 102 | + strcpy(buffer, "string\n"); |
|---|
| 119 | 103 | break; |
|---|
| 120 | 104 | |
|---|
| 121 | 105 | default: |
|---|
| 122 | | - strcpy(buffer, "???"); |
|---|
| 106 | + strcpy(buffer, "???\n"); |
|---|
| 123 | 107 | break; |
|---|
| 124 | 108 | } |
|---|
| 125 | 109 | |
|---|
| .. | .. |
|---|
| 337 | 321 | int dyn_guid_set; |
|---|
| 338 | 322 | struct kref usecount; |
|---|
| 339 | 323 | struct work_struct remove_work; |
|---|
| 324 | + unsigned char cc; /* completion code */ |
|---|
| 340 | 325 | }; |
|---|
| 341 | 326 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) |
|---|
| 342 | 327 | |
|---|
| .. | .. |
|---|
| 536 | 521 | unsigned int waiting_events_count; /* How many events in queue? */ |
|---|
| 537 | 522 | char delivering_events; |
|---|
| 538 | 523 | char event_msg_printed; |
|---|
| 524 | + |
|---|
| 525 | + /* How many users are waiting for events? */ |
|---|
| 539 | 526 | atomic_t event_waiters; |
|---|
| 540 | 527 | unsigned int ticks_to_req_ev; |
|---|
| 541 | | - int last_needs_timer; |
|---|
| 528 | + |
|---|
| 529 | + spinlock_t watch_lock; /* For dealing with watch stuff below. */ |
|---|
| 530 | + |
|---|
| 531 | + /* How many users are waiting for commands? */ |
|---|
| 532 | + unsigned int command_waiters; |
|---|
| 533 | + |
|---|
| 534 | + /* How many users are waiting for watchdogs? */ |
|---|
| 535 | + unsigned int watchdog_waiters; |
|---|
| 536 | + |
|---|
| 537 | + /* How many users are waiting for message responses? */ |
|---|
| 538 | + unsigned int response_waiters; |
|---|
| 539 | + |
|---|
| 540 | + /* |
|---|
| 541 | + * Tells what the lower layer has last been asked to watch for, |
|---|
| 542 | + * messages and/or watchdogs. Protected by watch_lock. |
|---|
| 543 | + */ |
|---|
| 544 | + unsigned int last_watch_mask; |
|---|
| 542 | 545 | |
|---|
| 543 | 546 | /* |
|---|
| 544 | 547 | * The event receiver for my BMC, only really used at panic |
|---|
| .. | .. |
|---|
| 621 | 624 | |
|---|
| 622 | 625 | static LIST_HEAD(ipmi_interfaces); |
|---|
| 623 | 626 | static DEFINE_MUTEX(ipmi_interfaces_mutex); |
|---|
| 624 | | -struct srcu_struct ipmi_interfaces_srcu; |
|---|
| 627 | +#define ipmi_interfaces_mutex_held() \ |
|---|
| 628 | + lockdep_is_held(&ipmi_interfaces_mutex) |
|---|
| 629 | +static struct srcu_struct ipmi_interfaces_srcu; |
|---|
| 625 | 630 | |
|---|
| 626 | 631 | /* |
|---|
| 627 | 632 | * List of watchers that want to know when smi's are added and deleted. |
|---|
| .. | .. |
|---|
| 890 | 895 | rv = -EINVAL; |
|---|
| 891 | 896 | } |
|---|
| 892 | 897 | ipmi_free_recv_msg(msg); |
|---|
| 893 | | - } else if (!oops_in_progress) { |
|---|
| 898 | + } else if (oops_in_progress) { |
|---|
| 894 | 899 | /* |
|---|
| 895 | 900 | * If we are running in the panic context, calling the |
|---|
| 896 | 901 | * receive handler doesn't much meaning and has a deadlock |
|---|
| 897 | 902 | * risk. At this moment, simply skip it in that case. |
|---|
| 898 | 903 | */ |
|---|
| 904 | + ipmi_free_recv_msg(msg); |
|---|
| 905 | + } else { |
|---|
| 899 | 906 | int index; |
|---|
| 900 | 907 | struct ipmi_user *user = acquire_ipmi_user(msg->user, &index); |
|---|
| 901 | 908 | |
|---|
| .. | .. |
|---|
| 930 | 937 | msg->msg.data_len = 1; |
|---|
| 931 | 938 | msg->msg.data = msg->msg_data; |
|---|
| 932 | 939 | deliver_local_response(intf, msg); |
|---|
| 940 | +} |
|---|
| 941 | + |
|---|
| 942 | +static void smi_add_watch(struct ipmi_smi *intf, unsigned int flags) |
|---|
| 943 | +{ |
|---|
| 944 | + unsigned long iflags; |
|---|
| 945 | + |
|---|
| 946 | + if (!intf->handlers->set_need_watch) |
|---|
| 947 | + return; |
|---|
| 948 | + |
|---|
| 949 | + spin_lock_irqsave(&intf->watch_lock, iflags); |
|---|
| 950 | + if (flags & IPMI_WATCH_MASK_CHECK_MESSAGES) |
|---|
| 951 | + intf->response_waiters++; |
|---|
| 952 | + |
|---|
| 953 | + if (flags & IPMI_WATCH_MASK_CHECK_WATCHDOG) |
|---|
| 954 | + intf->watchdog_waiters++; |
|---|
| 955 | + |
|---|
| 956 | + if (flags & IPMI_WATCH_MASK_CHECK_COMMANDS) |
|---|
| 957 | + intf->command_waiters++; |
|---|
| 958 | + |
|---|
| 959 | + if ((intf->last_watch_mask & flags) != flags) { |
|---|
| 960 | + intf->last_watch_mask |= flags; |
|---|
| 961 | + intf->handlers->set_need_watch(intf->send_info, |
|---|
| 962 | + intf->last_watch_mask); |
|---|
| 963 | + } |
|---|
| 964 | + spin_unlock_irqrestore(&intf->watch_lock, iflags); |
|---|
| 965 | +} |
|---|
| 966 | + |
|---|
| 967 | +static void smi_remove_watch(struct ipmi_smi *intf, unsigned int flags) |
|---|
| 968 | +{ |
|---|
| 969 | + unsigned long iflags; |
|---|
| 970 | + |
|---|
| 971 | + if (!intf->handlers->set_need_watch) |
|---|
| 972 | + return; |
|---|
| 973 | + |
|---|
| 974 | + spin_lock_irqsave(&intf->watch_lock, iflags); |
|---|
| 975 | + if (flags & IPMI_WATCH_MASK_CHECK_MESSAGES) |
|---|
| 976 | + intf->response_waiters--; |
|---|
| 977 | + |
|---|
| 978 | + if (flags & IPMI_WATCH_MASK_CHECK_WATCHDOG) |
|---|
| 979 | + intf->watchdog_waiters--; |
|---|
| 980 | + |
|---|
| 981 | + if (flags & IPMI_WATCH_MASK_CHECK_COMMANDS) |
|---|
| 982 | + intf->command_waiters--; |
|---|
| 983 | + |
|---|
| 984 | + flags = 0; |
|---|
| 985 | + if (intf->response_waiters) |
|---|
| 986 | + flags |= IPMI_WATCH_MASK_CHECK_MESSAGES; |
|---|
| 987 | + if (intf->watchdog_waiters) |
|---|
| 988 | + flags |= IPMI_WATCH_MASK_CHECK_WATCHDOG; |
|---|
| 989 | + if (intf->command_waiters) |
|---|
| 990 | + flags |= IPMI_WATCH_MASK_CHECK_COMMANDS; |
|---|
| 991 | + |
|---|
| 992 | + if (intf->last_watch_mask != flags) { |
|---|
| 993 | + intf->last_watch_mask = flags; |
|---|
| 994 | + intf->handlers->set_need_watch(intf->send_info, |
|---|
| 995 | + intf->last_watch_mask); |
|---|
| 996 | + } |
|---|
| 997 | + spin_unlock_irqrestore(&intf->watch_lock, iflags); |
|---|
| 933 | 998 | } |
|---|
| 934 | 999 | |
|---|
| 935 | 1000 | /* |
|---|
| .. | .. |
|---|
| 975 | 1040 | *seq = i; |
|---|
| 976 | 1041 | *seqid = intf->seq_table[i].seqid; |
|---|
| 977 | 1042 | intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ; |
|---|
| 1043 | + smi_add_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 978 | 1044 | need_waiter(intf); |
|---|
| 979 | 1045 | } else { |
|---|
| 980 | 1046 | rv = -EAGAIN; |
|---|
| .. | .. |
|---|
| 1013 | 1079 | && (ipmi_addr_equal(addr, &msg->addr))) { |
|---|
| 1014 | 1080 | *recv_msg = msg; |
|---|
| 1015 | 1081 | intf->seq_table[seq].inuse = 0; |
|---|
| 1082 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 1016 | 1083 | rv = 0; |
|---|
| 1017 | 1084 | } |
|---|
| 1018 | 1085 | } |
|---|
| .. | .. |
|---|
| 1074 | 1141 | struct seq_table *ent = &intf->seq_table[seq]; |
|---|
| 1075 | 1142 | |
|---|
| 1076 | 1143 | ent->inuse = 0; |
|---|
| 1144 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 1077 | 1145 | msg = ent->recv_msg; |
|---|
| 1078 | 1146 | rv = 0; |
|---|
| 1079 | 1147 | } |
|---|
| .. | .. |
|---|
| 1084 | 1152 | |
|---|
| 1085 | 1153 | return rv; |
|---|
| 1086 | 1154 | } |
|---|
| 1087 | | - |
|---|
| 1088 | 1155 | |
|---|
| 1089 | 1156 | static void free_user_work(struct work_struct *work) |
|---|
| 1090 | 1157 | { |
|---|
| .. | .. |
|---|
| 1162 | 1229 | spin_lock_irqsave(&intf->seq_lock, flags); |
|---|
| 1163 | 1230 | list_add_rcu(&new_user->link, &intf->users); |
|---|
| 1164 | 1231 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
|---|
| 1165 | | - if (handler->ipmi_watchdog_pretimeout) { |
|---|
| 1232 | + if (handler->ipmi_watchdog_pretimeout) |
|---|
| 1166 | 1233 | /* User wants pretimeouts, so make sure to watch for them. */ |
|---|
| 1167 | | - if (atomic_inc_return(&intf->event_waiters) == 1) |
|---|
| 1168 | | - need_waiter(intf); |
|---|
| 1169 | | - } |
|---|
| 1234 | + smi_add_watch(intf, IPMI_WATCH_MASK_CHECK_WATCHDOG); |
|---|
| 1170 | 1235 | srcu_read_unlock(&ipmi_interfaces_srcu, index); |
|---|
| 1171 | 1236 | *user = new_user; |
|---|
| 1172 | 1237 | return 0; |
|---|
| .. | .. |
|---|
| 1238 | 1303 | user->handler->shutdown(user->handler_data); |
|---|
| 1239 | 1304 | |
|---|
| 1240 | 1305 | if (user->handler->ipmi_watchdog_pretimeout) |
|---|
| 1241 | | - atomic_dec(&intf->event_waiters); |
|---|
| 1306 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_WATCHDOG); |
|---|
| 1242 | 1307 | |
|---|
| 1243 | 1308 | if (user->gets_events) |
|---|
| 1244 | 1309 | atomic_dec(&intf->event_waiters); |
|---|
| .. | .. |
|---|
| 1251 | 1316 | if (intf->seq_table[i].inuse |
|---|
| 1252 | 1317 | && (intf->seq_table[i].recv_msg->user == user)) { |
|---|
| 1253 | 1318 | intf->seq_table[i].inuse = 0; |
|---|
| 1319 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 1254 | 1320 | ipmi_free_recv_msg(intf->seq_table[i].recv_msg); |
|---|
| 1255 | 1321 | } |
|---|
| 1256 | 1322 | } |
|---|
| .. | .. |
|---|
| 1263 | 1329 | * synchronize_srcu()) then free everything in that list. |
|---|
| 1264 | 1330 | */ |
|---|
| 1265 | 1331 | mutex_lock(&intf->cmd_rcvrs_mutex); |
|---|
| 1266 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1332 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1333 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1267 | 1334 | if (rcvr->user == user) { |
|---|
| 1268 | 1335 | list_del_rcu(&rcvr->link); |
|---|
| 1269 | 1336 | rcvr->next = rcvrs; |
|---|
| .. | .. |
|---|
| 1509 | 1576 | list_move_tail(&msg->link, &msgs); |
|---|
| 1510 | 1577 | intf->waiting_events_count = 0; |
|---|
| 1511 | 1578 | if (intf->event_msg_printed) { |
|---|
| 1512 | | - dev_warn(intf->si_dev, |
|---|
| 1513 | | - PFX "Event queue no longer full\n"); |
|---|
| 1579 | + dev_warn(intf->si_dev, "Event queue no longer full\n"); |
|---|
| 1514 | 1580 | intf->event_msg_printed = 0; |
|---|
| 1515 | 1581 | } |
|---|
| 1516 | 1582 | |
|---|
| .. | .. |
|---|
| 1542 | 1608 | { |
|---|
| 1543 | 1609 | struct cmd_rcvr *rcvr; |
|---|
| 1544 | 1610 | |
|---|
| 1545 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1611 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1612 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1546 | 1613 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) |
|---|
| 1547 | 1614 | && (rcvr->chans & (1 << chan))) |
|---|
| 1548 | 1615 | return rcvr; |
|---|
| .. | .. |
|---|
| 1557 | 1624 | { |
|---|
| 1558 | 1625 | struct cmd_rcvr *rcvr; |
|---|
| 1559 | 1626 | |
|---|
| 1560 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1627 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1628 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1561 | 1629 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) |
|---|
| 1562 | 1630 | && (rcvr->chans & chans)) |
|---|
| 1563 | 1631 | return 0; |
|---|
| .. | .. |
|---|
| 1595 | 1663 | goto out_unlock; |
|---|
| 1596 | 1664 | } |
|---|
| 1597 | 1665 | |
|---|
| 1598 | | - if (atomic_inc_return(&intf->event_waiters) == 1) |
|---|
| 1599 | | - need_waiter(intf); |
|---|
| 1666 | + smi_add_watch(intf, IPMI_WATCH_MASK_CHECK_COMMANDS); |
|---|
| 1600 | 1667 | |
|---|
| 1601 | 1668 | list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); |
|---|
| 1602 | 1669 | |
|---|
| .. | .. |
|---|
| 1646 | 1713 | synchronize_rcu(); |
|---|
| 1647 | 1714 | release_ipmi_user(user, index); |
|---|
| 1648 | 1715 | while (rcvrs) { |
|---|
| 1649 | | - atomic_dec(&intf->event_waiters); |
|---|
| 1716 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_COMMANDS); |
|---|
| 1650 | 1717 | rcvr = rcvrs; |
|---|
| 1651 | 1718 | rcvrs = rcvr->next; |
|---|
| 1652 | 1719 | kfree(rcvr); |
|---|
| .. | .. |
|---|
| 1763 | 1830 | return smi_msg; |
|---|
| 1764 | 1831 | } |
|---|
| 1765 | 1832 | |
|---|
| 1766 | | - |
|---|
| 1767 | 1833 | static void smi_send(struct ipmi_smi *intf, |
|---|
| 1768 | 1834 | const struct ipmi_smi_handlers *handlers, |
|---|
| 1769 | 1835 | struct ipmi_smi_msg *smi_msg, int priority) |
|---|
| 1770 | 1836 | { |
|---|
| 1771 | 1837 | int run_to_completion = intf->run_to_completion; |
|---|
| 1838 | + unsigned long flags = 0; |
|---|
| 1772 | 1839 | |
|---|
| 1773 | | - if (run_to_completion) { |
|---|
| 1774 | | - smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1775 | | - } else { |
|---|
| 1776 | | - unsigned long flags; |
|---|
| 1777 | | - |
|---|
| 1840 | + if (!run_to_completion) |
|---|
| 1778 | 1841 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); |
|---|
| 1779 | | - smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1842 | + smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1843 | + |
|---|
| 1844 | + if (!run_to_completion) |
|---|
| 1780 | 1845 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 1781 | | - } |
|---|
| 1782 | 1846 | |
|---|
| 1783 | 1847 | if (smi_msg) |
|---|
| 1784 | 1848 | handlers->sender(intf->send_info, smi_msg); |
|---|
| .. | .. |
|---|
| 2158 | 2222 | else { |
|---|
| 2159 | 2223 | smi_msg = ipmi_alloc_smi_msg(); |
|---|
| 2160 | 2224 | if (smi_msg == NULL) { |
|---|
| 2161 | | - ipmi_free_recv_msg(recv_msg); |
|---|
| 2225 | + if (!supplied_recv) |
|---|
| 2226 | + ipmi_free_recv_msg(recv_msg); |
|---|
| 2162 | 2227 | rv = -ENOMEM; |
|---|
| 2163 | 2228 | goto out; |
|---|
| 2164 | 2229 | } |
|---|
| .. | .. |
|---|
| 2202 | 2267 | ipmi_free_smi_msg(smi_msg); |
|---|
| 2203 | 2268 | ipmi_free_recv_msg(recv_msg); |
|---|
| 2204 | 2269 | } else { |
|---|
| 2205 | | - ipmi_debug_msg("Send", smi_msg->data, smi_msg->data_size); |
|---|
| 2270 | + pr_debug("Send: %*ph\n", smi_msg->data_size, smi_msg->data); |
|---|
| 2206 | 2271 | |
|---|
| 2207 | 2272 | smi_send(intf, intf->handlers, smi_msg, priority); |
|---|
| 2208 | 2273 | } |
|---|
| .. | .. |
|---|
| 2312 | 2377 | || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE) |
|---|
| 2313 | 2378 | || (msg->msg.cmd != IPMI_GET_DEVICE_ID_CMD)) { |
|---|
| 2314 | 2379 | dev_warn(intf->si_dev, |
|---|
| 2315 | | - PFX "invalid device_id msg: addr_type=%d netfn=%x cmd=%x\n", |
|---|
| 2316 | | - msg->addr.addr_type, msg->msg.netfn, msg->msg.cmd); |
|---|
| 2380 | + "invalid device_id msg: addr_type=%d netfn=%x cmd=%x\n", |
|---|
| 2381 | + msg->addr.addr_type, msg->msg.netfn, msg->msg.cmd); |
|---|
| 2317 | 2382 | return; |
|---|
| 2318 | 2383 | } |
|---|
| 2319 | 2384 | |
|---|
| 2320 | 2385 | rv = ipmi_demangle_device_id(msg->msg.netfn, msg->msg.cmd, |
|---|
| 2321 | 2386 | msg->msg.data, msg->msg.data_len, &intf->bmc->fetch_id); |
|---|
| 2322 | 2387 | if (rv) { |
|---|
| 2323 | | - dev_warn(intf->si_dev, |
|---|
| 2324 | | - PFX "device id demangle failed: %d\n", rv); |
|---|
| 2388 | + dev_warn(intf->si_dev, "device id demangle failed: %d\n", rv); |
|---|
| 2389 | + /* record completion code when error */ |
|---|
| 2390 | + intf->bmc->cc = msg->msg.data[0]; |
|---|
| 2325 | 2391 | intf->bmc->dyn_id_set = 0; |
|---|
| 2326 | 2392 | } else { |
|---|
| 2327 | 2393 | /* |
|---|
| .. | .. |
|---|
| 2367 | 2433 | static int __get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc) |
|---|
| 2368 | 2434 | { |
|---|
| 2369 | 2435 | int rv; |
|---|
| 2370 | | - |
|---|
| 2371 | | - bmc->dyn_id_set = 2; |
|---|
| 2436 | + unsigned int retry_count = 0; |
|---|
| 2372 | 2437 | |
|---|
| 2373 | 2438 | intf->null_user_handler = bmc_device_id_handler; |
|---|
| 2374 | 2439 | |
|---|
| 2440 | +retry: |
|---|
| 2441 | + bmc->cc = 0; |
|---|
| 2442 | + bmc->dyn_id_set = 2; |
|---|
| 2443 | + |
|---|
| 2375 | 2444 | rv = send_get_device_id_cmd(intf); |
|---|
| 2376 | 2445 | if (rv) |
|---|
| 2377 | | - return rv; |
|---|
| 2446 | + goto out_reset_handler; |
|---|
| 2378 | 2447 | |
|---|
| 2379 | 2448 | wait_event(intf->waitq, bmc->dyn_id_set != 2); |
|---|
| 2380 | 2449 | |
|---|
| 2381 | | - if (!bmc->dyn_id_set) |
|---|
| 2450 | + if (!bmc->dyn_id_set) { |
|---|
| 2451 | + if ((bmc->cc == IPMI_DEVICE_IN_FW_UPDATE_ERR |
|---|
| 2452 | + || bmc->cc == IPMI_DEVICE_IN_INIT_ERR |
|---|
| 2453 | + || bmc->cc == IPMI_NOT_IN_MY_STATE_ERR) |
|---|
| 2454 | + && ++retry_count <= GET_DEVICE_ID_MAX_RETRY) { |
|---|
| 2455 | + msleep(500); |
|---|
| 2456 | + dev_warn(intf->si_dev, |
|---|
| 2457 | + "BMC returned 0x%2.2x, retry get bmc device id\n", |
|---|
| 2458 | + bmc->cc); |
|---|
| 2459 | + goto retry; |
|---|
| 2460 | + } |
|---|
| 2461 | + |
|---|
| 2382 | 2462 | rv = -EIO; /* Something went wrong in the fetch. */ |
|---|
| 2463 | + } |
|---|
| 2383 | 2464 | |
|---|
| 2384 | 2465 | /* dyn_id_set makes the id data available. */ |
|---|
| 2385 | 2466 | smp_rmb(); |
|---|
| 2386 | 2467 | |
|---|
| 2468 | +out_reset_handler: |
|---|
| 2387 | 2469 | intf->null_user_handler = NULL; |
|---|
| 2388 | 2470 | |
|---|
| 2389 | 2471 | return rv; |
|---|
| .. | .. |
|---|
| 2703 | 2785 | if (!guid_set) |
|---|
| 2704 | 2786 | return -ENOENT; |
|---|
| 2705 | 2787 | |
|---|
| 2706 | | - return snprintf(buf, 38, "%pUl\n", guid.b); |
|---|
| 2788 | + return snprintf(buf, UUID_STRING_LEN + 1 + 1, "%pUl\n", &guid); |
|---|
| 2707 | 2789 | } |
|---|
| 2708 | 2790 | static DEVICE_ATTR_RO(guid); |
|---|
| 2709 | 2791 | |
|---|
| .. | .. |
|---|
| 2758 | 2840 | .groups = bmc_dev_attr_groups, |
|---|
| 2759 | 2841 | }; |
|---|
| 2760 | 2842 | |
|---|
| 2761 | | -static int __find_bmc_guid(struct device *dev, void *data) |
|---|
| 2843 | +static int __find_bmc_guid(struct device *dev, const void *data) |
|---|
| 2762 | 2844 | { |
|---|
| 2763 | | - guid_t *guid = data; |
|---|
| 2845 | + const guid_t *guid = data; |
|---|
| 2764 | 2846 | struct bmc_device *bmc; |
|---|
| 2765 | 2847 | int rv; |
|---|
| 2766 | 2848 | |
|---|
| .. | .. |
|---|
| 2796 | 2878 | unsigned char device_id; |
|---|
| 2797 | 2879 | }; |
|---|
| 2798 | 2880 | |
|---|
| 2799 | | -static int __find_bmc_prod_dev_id(struct device *dev, void *data) |
|---|
| 2881 | +static int __find_bmc_prod_dev_id(struct device *dev, const void *data) |
|---|
| 2800 | 2882 | { |
|---|
| 2801 | | - struct prod_dev_id *cid = data; |
|---|
| 2883 | + const struct prod_dev_id *cid = data; |
|---|
| 2802 | 2884 | struct bmc_device *bmc; |
|---|
| 2803 | 2885 | int rv; |
|---|
| 2804 | 2886 | |
|---|
| .. | .. |
|---|
| 2944 | 3026 | mutex_unlock(&bmc->dyn_mutex); |
|---|
| 2945 | 3027 | |
|---|
| 2946 | 3028 | dev_info(intf->si_dev, |
|---|
| 2947 | | - "ipmi: interfacing existing BMC (man_id: 0x%6.6x," |
|---|
| 2948 | | - " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", |
|---|
| 3029 | + "interfacing existing BMC (man_id: 0x%6.6x, prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", |
|---|
| 2949 | 3030 | bmc->id.manufacturer_id, |
|---|
| 2950 | 3031 | bmc->id.product_id, |
|---|
| 2951 | 3032 | bmc->id.device_id); |
|---|
| .. | .. |
|---|
| 2987 | 3068 | rv = platform_device_register(&bmc->pdev); |
|---|
| 2988 | 3069 | if (rv) { |
|---|
| 2989 | 3070 | dev_err(intf->si_dev, |
|---|
| 2990 | | - PFX " Unable to register bmc device: %d\n", |
|---|
| 3071 | + "Unable to register bmc device: %d\n", |
|---|
| 2991 | 3072 | rv); |
|---|
| 2992 | 3073 | goto out_list_del; |
|---|
| 2993 | 3074 | } |
|---|
| .. | .. |
|---|
| 3005 | 3086 | */ |
|---|
| 3006 | 3087 | rv = sysfs_create_link(&intf->si_dev->kobj, &bmc->pdev.dev.kobj, "bmc"); |
|---|
| 3007 | 3088 | if (rv) { |
|---|
| 3008 | | - dev_err(intf->si_dev, |
|---|
| 3009 | | - PFX "Unable to create bmc symlink: %d\n", rv); |
|---|
| 3089 | + dev_err(intf->si_dev, "Unable to create bmc symlink: %d\n", rv); |
|---|
| 3010 | 3090 | goto out_put_bmc; |
|---|
| 3011 | 3091 | } |
|---|
| 3012 | 3092 | |
|---|
| .. | .. |
|---|
| 3015 | 3095 | intf->my_dev_name = kasprintf(GFP_KERNEL, "ipmi%d", intf_num); |
|---|
| 3016 | 3096 | if (!intf->my_dev_name) { |
|---|
| 3017 | 3097 | rv = -ENOMEM; |
|---|
| 3018 | | - dev_err(intf->si_dev, |
|---|
| 3019 | | - PFX "Unable to allocate link from BMC: %d\n", rv); |
|---|
| 3098 | + dev_err(intf->si_dev, "Unable to allocate link from BMC: %d\n", |
|---|
| 3099 | + rv); |
|---|
| 3020 | 3100 | goto out_unlink1; |
|---|
| 3021 | 3101 | } |
|---|
| 3022 | 3102 | |
|---|
| 3023 | 3103 | rv = sysfs_create_link(&bmc->pdev.dev.kobj, &intf->si_dev->kobj, |
|---|
| 3024 | 3104 | intf->my_dev_name); |
|---|
| 3025 | 3105 | if (rv) { |
|---|
| 3026 | | - kfree(intf->my_dev_name); |
|---|
| 3027 | | - intf->my_dev_name = NULL; |
|---|
| 3028 | | - dev_err(intf->si_dev, |
|---|
| 3029 | | - PFX "Unable to create symlink to bmc: %d\n", rv); |
|---|
| 3106 | + dev_err(intf->si_dev, "Unable to create symlink to bmc: %d\n", |
|---|
| 3107 | + rv); |
|---|
| 3030 | 3108 | goto out_free_my_dev_name; |
|---|
| 3031 | 3109 | } |
|---|
| 3032 | 3110 | |
|---|
| .. | .. |
|---|
| 3107 | 3185 | goto out; |
|---|
| 3108 | 3186 | } |
|---|
| 3109 | 3187 | |
|---|
| 3110 | | - if (msg->msg.data_len < 17) { |
|---|
| 3188 | + if (msg->msg.data_len < UUID_SIZE + 1) { |
|---|
| 3111 | 3189 | bmc->dyn_guid_set = 0; |
|---|
| 3112 | 3190 | dev_warn(intf->si_dev, |
|---|
| 3113 | | - PFX "The GUID response from the BMC was too short, it was %d but should have been 17. Assuming GUID is not available.\n", |
|---|
| 3114 | | - msg->msg.data_len); |
|---|
| 3191 | + "The GUID response from the BMC was too short, it was %d but should have been %d. Assuming GUID is not available.\n", |
|---|
| 3192 | + msg->msg.data_len, UUID_SIZE + 1); |
|---|
| 3115 | 3193 | goto out; |
|---|
| 3116 | 3194 | } |
|---|
| 3117 | 3195 | |
|---|
| 3118 | | - memcpy(bmc->fetch_guid.b, msg->msg.data + 1, 16); |
|---|
| 3196 | + import_guid(&bmc->fetch_guid, msg->msg.data + 1); |
|---|
| 3119 | 3197 | /* |
|---|
| 3120 | 3198 | * Make sure the guid data is available before setting |
|---|
| 3121 | 3199 | * dyn_guid_set. |
|---|
| .. | .. |
|---|
| 3190 | 3268 | /* It's the one we want */ |
|---|
| 3191 | 3269 | if (msg->msg.data[0] != 0) { |
|---|
| 3192 | 3270 | /* Got an error from the channel, just go on. */ |
|---|
| 3193 | | - |
|---|
| 3194 | 3271 | if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { |
|---|
| 3195 | 3272 | /* |
|---|
| 3196 | 3273 | * If the MC does not support this |
|---|
| .. | .. |
|---|
| 3234 | 3311 | if (rv) { |
|---|
| 3235 | 3312 | /* Got an error somehow, just give up. */ |
|---|
| 3236 | 3313 | dev_warn(intf->si_dev, |
|---|
| 3237 | | - PFX "Error sending channel information for channel %d: %d\n", |
|---|
| 3314 | + "Error sending channel information for channel %d: %d\n", |
|---|
| 3238 | 3315 | intf->curr_channel, rv); |
|---|
| 3239 | 3316 | |
|---|
| 3240 | 3317 | intf->channel_list = intf->wchannels + set; |
|---|
| .. | .. |
|---|
| 3274 | 3351 | dev_warn(intf->si_dev, |
|---|
| 3275 | 3352 | "Error sending channel information for channel 0, %d\n", |
|---|
| 3276 | 3353 | rv); |
|---|
| 3354 | + intf->null_user_handler = NULL; |
|---|
| 3277 | 3355 | return -EIO; |
|---|
| 3278 | 3356 | } |
|---|
| 3279 | 3357 | |
|---|
| .. | .. |
|---|
| 3375 | 3453 | intf->curr_seq = 0; |
|---|
| 3376 | 3454 | spin_lock_init(&intf->waiting_rcv_msgs_lock); |
|---|
| 3377 | 3455 | INIT_LIST_HEAD(&intf->waiting_rcv_msgs); |
|---|
| 3378 | | - tasklet_init(&intf->recv_tasklet, |
|---|
| 3379 | | - smi_recv_tasklet, |
|---|
| 3380 | | - (unsigned long) intf); |
|---|
| 3456 | + tasklet_setup(&intf->recv_tasklet, |
|---|
| 3457 | + smi_recv_tasklet); |
|---|
| 3381 | 3458 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); |
|---|
| 3382 | 3459 | spin_lock_init(&intf->xmit_msgs_lock); |
|---|
| 3383 | 3460 | INIT_LIST_HEAD(&intf->xmit_msgs); |
|---|
| 3384 | 3461 | INIT_LIST_HEAD(&intf->hp_xmit_msgs); |
|---|
| 3385 | 3462 | spin_lock_init(&intf->events_lock); |
|---|
| 3463 | + spin_lock_init(&intf->watch_lock); |
|---|
| 3386 | 3464 | atomic_set(&intf->event_waiters, 0); |
|---|
| 3387 | 3465 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
|---|
| 3388 | 3466 | INIT_LIST_HEAD(&intf->waiting_events); |
|---|
| .. | .. |
|---|
| 3398 | 3476 | /* Look for a hole in the numbers. */ |
|---|
| 3399 | 3477 | i = 0; |
|---|
| 3400 | 3478 | link = &ipmi_interfaces; |
|---|
| 3401 | | - list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) { |
|---|
| 3479 | + list_for_each_entry_rcu(tintf, &ipmi_interfaces, link, |
|---|
| 3480 | + ipmi_interfaces_mutex_held()) { |
|---|
| 3402 | 3481 | if (tintf->intf_num != i) { |
|---|
| 3403 | 3482 | link = &tintf->link; |
|---|
| 3404 | 3483 | break; |
|---|
| .. | .. |
|---|
| 3671 | 3750 | msg->data[10] = ipmb_checksum(&msg->data[6], 4); |
|---|
| 3672 | 3751 | msg->data_size = 11; |
|---|
| 3673 | 3752 | |
|---|
| 3674 | | - ipmi_debug_msg("Invalid command:", msg->data, msg->data_size); |
|---|
| 3753 | + pr_debug("Invalid command: %*ph\n", msg->data_size, msg->data); |
|---|
| 3675 | 3754 | |
|---|
| 3676 | 3755 | rcu_read_lock(); |
|---|
| 3677 | 3756 | if (!intf->in_shutdown) { |
|---|
| .. | .. |
|---|
| 4107 | 4186 | * message. |
|---|
| 4108 | 4187 | */ |
|---|
| 4109 | 4188 | dev_warn(intf->si_dev, |
|---|
| 4110 | | - PFX "Event queue full, discarding incoming events\n"); |
|---|
| 4189 | + "Event queue full, discarding incoming events\n"); |
|---|
| 4111 | 4190 | intf->event_msg_printed = 1; |
|---|
| 4112 | 4191 | } |
|---|
| 4113 | 4192 | |
|---|
| .. | .. |
|---|
| 4126 | 4205 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
|---|
| 4127 | 4206 | if (recv_msg == NULL) { |
|---|
| 4128 | 4207 | dev_warn(intf->si_dev, |
|---|
| 4129 | | - "IPMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vender for assistance\n"); |
|---|
| 4208 | + "IPMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); |
|---|
| 4130 | 4209 | return 0; |
|---|
| 4131 | 4210 | } |
|---|
| 4132 | 4211 | |
|---|
| .. | .. |
|---|
| 4158 | 4237 | int requeue; |
|---|
| 4159 | 4238 | int chan; |
|---|
| 4160 | 4239 | |
|---|
| 4161 | | - ipmi_debug_msg("Recv:", msg->rsp, msg->rsp_size); |
|---|
| 4162 | | - if (msg->rsp_size < 2) { |
|---|
| 4240 | + pr_debug("Recv: %*ph\n", msg->rsp_size, msg->rsp); |
|---|
| 4241 | + |
|---|
| 4242 | + if ((msg->data_size >= 2) |
|---|
| 4243 | + && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
|---|
| 4244 | + && (msg->data[1] == IPMI_SEND_MSG_CMD) |
|---|
| 4245 | + && (msg->user_data == NULL)) { |
|---|
| 4246 | + |
|---|
| 4247 | + if (intf->in_shutdown) |
|---|
| 4248 | + goto free_msg; |
|---|
| 4249 | + |
|---|
| 4250 | + /* |
|---|
| 4251 | + * This is the local response to a command send, start |
|---|
| 4252 | + * the timer for these. The user_data will not be |
|---|
| 4253 | + * NULL if this is a response send, and we will let |
|---|
| 4254 | + * response sends just go through. |
|---|
| 4255 | + */ |
|---|
| 4256 | + |
|---|
| 4257 | + /* |
|---|
| 4258 | + * Check for errors, if we get certain errors (ones |
|---|
| 4259 | + * that mean basically we can try again later), we |
|---|
| 4260 | + * ignore them and start the timer. Otherwise we |
|---|
| 4261 | + * report the error immediately. |
|---|
| 4262 | + */ |
|---|
| 4263 | + if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) |
|---|
| 4264 | + && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) |
|---|
| 4265 | + && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) |
|---|
| 4266 | + && (msg->rsp[2] != IPMI_BUS_ERR) |
|---|
| 4267 | + && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { |
|---|
| 4268 | + int ch = msg->rsp[3] & 0xf; |
|---|
| 4269 | + struct ipmi_channel *chans; |
|---|
| 4270 | + |
|---|
| 4271 | + /* Got an error sending the message, handle it. */ |
|---|
| 4272 | + |
|---|
| 4273 | + chans = READ_ONCE(intf->channel_list)->c; |
|---|
| 4274 | + if ((chans[ch].medium == IPMI_CHANNEL_MEDIUM_8023LAN) |
|---|
| 4275 | + || (chans[ch].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) |
|---|
| 4276 | + ipmi_inc_stat(intf, sent_lan_command_errs); |
|---|
| 4277 | + else |
|---|
| 4278 | + ipmi_inc_stat(intf, sent_ipmb_command_errs); |
|---|
| 4279 | + intf_err_seq(intf, msg->msgid, msg->rsp[2]); |
|---|
| 4280 | + } else |
|---|
| 4281 | + /* The message was sent, start the timer. */ |
|---|
| 4282 | + intf_start_seq_timer(intf, msg->msgid); |
|---|
| 4283 | +free_msg: |
|---|
| 4284 | + requeue = 0; |
|---|
| 4285 | + goto out; |
|---|
| 4286 | + |
|---|
| 4287 | + } else if (msg->rsp_size < 2) { |
|---|
| 4163 | 4288 | /* Message is too small to be correct. */ |
|---|
| 4164 | 4289 | dev_warn(intf->si_dev, |
|---|
| 4165 | | - PFX "BMC returned to small a message for netfn %x cmd %x, got %d bytes\n", |
|---|
| 4290 | + "BMC returned too small a message for netfn %x cmd %x, got %d bytes\n", |
|---|
| 4166 | 4291 | (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size); |
|---|
| 4167 | 4292 | |
|---|
| 4168 | 4293 | /* Generate an error response for the message. */ |
|---|
| .. | .. |
|---|
| 4177 | 4302 | * marginally correct. |
|---|
| 4178 | 4303 | */ |
|---|
| 4179 | 4304 | dev_warn(intf->si_dev, |
|---|
| 4180 | | - PFX "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", |
|---|
| 4305 | + "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", |
|---|
| 4181 | 4306 | (msg->data[0] >> 2) | 1, msg->data[1], |
|---|
| 4182 | 4307 | msg->rsp[0] >> 2, msg->rsp[1]); |
|---|
| 4183 | 4308 | |
|---|
| .. | .. |
|---|
| 4364 | 4489 | } |
|---|
| 4365 | 4490 | } |
|---|
| 4366 | 4491 | |
|---|
| 4367 | | -static void smi_recv_tasklet(unsigned long val) |
|---|
| 4492 | +static void smi_recv_tasklet(struct tasklet_struct *t) |
|---|
| 4368 | 4493 | { |
|---|
| 4369 | 4494 | unsigned long flags = 0; /* keep us warning-free. */ |
|---|
| 4370 | | - struct ipmi_smi *intf = (struct ipmi_smi *) val; |
|---|
| 4495 | + struct ipmi_smi *intf = from_tasklet(intf, t, recv_tasklet); |
|---|
| 4371 | 4496 | int run_to_completion = intf->run_to_completion; |
|---|
| 4372 | 4497 | struct ipmi_smi_msg *newmsg = NULL; |
|---|
| 4373 | 4498 | |
|---|
| .. | .. |
|---|
| 4398 | 4523 | intf->curr_msg = newmsg; |
|---|
| 4399 | 4524 | } |
|---|
| 4400 | 4525 | } |
|---|
| 4526 | + |
|---|
| 4401 | 4527 | if (!run_to_completion) |
|---|
| 4402 | 4528 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 4403 | 4529 | if (newmsg) |
|---|
| .. | .. |
|---|
| 4415 | 4541 | unsigned long flags = 0; /* keep us warning-free. */ |
|---|
| 4416 | 4542 | int run_to_completion = intf->run_to_completion; |
|---|
| 4417 | 4543 | |
|---|
| 4418 | | - if ((msg->data_size >= 2) |
|---|
| 4419 | | - && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
|---|
| 4420 | | - && (msg->data[1] == IPMI_SEND_MSG_CMD) |
|---|
| 4421 | | - && (msg->user_data == NULL)) { |
|---|
| 4422 | | - |
|---|
| 4423 | | - if (intf->in_shutdown) |
|---|
| 4424 | | - goto free_msg; |
|---|
| 4425 | | - |
|---|
| 4426 | | - /* |
|---|
| 4427 | | - * This is the local response to a command send, start |
|---|
| 4428 | | - * the timer for these. The user_data will not be |
|---|
| 4429 | | - * NULL if this is a response send, and we will let |
|---|
| 4430 | | - * response sends just go through. |
|---|
| 4431 | | - */ |
|---|
| 4432 | | - |
|---|
| 4433 | | - /* |
|---|
| 4434 | | - * Check for errors, if we get certain errors (ones |
|---|
| 4435 | | - * that mean basically we can try again later), we |
|---|
| 4436 | | - * ignore them and start the timer. Otherwise we |
|---|
| 4437 | | - * report the error immediately. |
|---|
| 4438 | | - */ |
|---|
| 4439 | | - if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) |
|---|
| 4440 | | - && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) |
|---|
| 4441 | | - && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) |
|---|
| 4442 | | - && (msg->rsp[2] != IPMI_BUS_ERR) |
|---|
| 4443 | | - && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { |
|---|
| 4444 | | - int ch = msg->rsp[3] & 0xf; |
|---|
| 4445 | | - struct ipmi_channel *chans; |
|---|
| 4446 | | - |
|---|
| 4447 | | - /* Got an error sending the message, handle it. */ |
|---|
| 4448 | | - |
|---|
| 4449 | | - chans = READ_ONCE(intf->channel_list)->c; |
|---|
| 4450 | | - if ((chans[ch].medium == IPMI_CHANNEL_MEDIUM_8023LAN) |
|---|
| 4451 | | - || (chans[ch].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) |
|---|
| 4452 | | - ipmi_inc_stat(intf, sent_lan_command_errs); |
|---|
| 4453 | | - else |
|---|
| 4454 | | - ipmi_inc_stat(intf, sent_ipmb_command_errs); |
|---|
| 4455 | | - intf_err_seq(intf, msg->msgid, msg->rsp[2]); |
|---|
| 4456 | | - } else |
|---|
| 4457 | | - /* The message was sent, start the timer. */ |
|---|
| 4458 | | - intf_start_seq_timer(intf, msg->msgid); |
|---|
| 4459 | | - |
|---|
| 4460 | | -free_msg: |
|---|
| 4461 | | - ipmi_free_smi_msg(msg); |
|---|
| 4462 | | - } else { |
|---|
| 4463 | | - /* |
|---|
| 4464 | | - * To preserve message order, we keep a queue and deliver from |
|---|
| 4465 | | - * a tasklet. |
|---|
| 4466 | | - */ |
|---|
| 4467 | | - if (!run_to_completion) |
|---|
| 4468 | | - spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); |
|---|
| 4469 | | - list_add_tail(&msg->link, &intf->waiting_rcv_msgs); |
|---|
| 4470 | | - if (!run_to_completion) |
|---|
| 4471 | | - spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, |
|---|
| 4472 | | - flags); |
|---|
| 4473 | | - } |
|---|
| 4544 | + /* |
|---|
| 4545 | + * To preserve message order, we keep a queue and deliver from |
|---|
| 4546 | + * a tasklet. |
|---|
| 4547 | + */ |
|---|
| 4548 | + if (!run_to_completion) |
|---|
| 4549 | + spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); |
|---|
| 4550 | + list_add_tail(&msg->link, &intf->waiting_rcv_msgs); |
|---|
| 4551 | + if (!run_to_completion) |
|---|
| 4552 | + spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, |
|---|
| 4553 | + flags); |
|---|
| 4474 | 4554 | |
|---|
| 4475 | 4555 | if (!run_to_completion) |
|---|
| 4476 | 4556 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); |
|---|
| .. | .. |
|---|
| 4484 | 4564 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 4485 | 4565 | |
|---|
| 4486 | 4566 | if (run_to_completion) |
|---|
| 4487 | | - smi_recv_tasklet((unsigned long) intf); |
|---|
| 4567 | + smi_recv_tasklet(&intf->recv_tasklet); |
|---|
| 4488 | 4568 | else |
|---|
| 4489 | 4569 | tasklet_schedule(&intf->recv_tasklet); |
|---|
| 4490 | 4570 | } |
|---|
| .. | .. |
|---|
| 4516 | 4596 | smi_msg->data_size = recv_msg->msg.data_len; |
|---|
| 4517 | 4597 | smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); |
|---|
| 4518 | 4598 | |
|---|
| 4519 | | - ipmi_debug_msg("Resend: ", smi_msg->data, smi_msg->data_size); |
|---|
| 4599 | + pr_debug("Resend: %*ph\n", smi_msg->data_size, smi_msg->data); |
|---|
| 4520 | 4600 | |
|---|
| 4521 | 4601 | return smi_msg; |
|---|
| 4522 | 4602 | } |
|---|
| .. | .. |
|---|
| 4525 | 4605 | struct list_head *timeouts, |
|---|
| 4526 | 4606 | unsigned long timeout_period, |
|---|
| 4527 | 4607 | int slot, unsigned long *flags, |
|---|
| 4528 | | - unsigned int *waiting_msgs) |
|---|
| 4608 | + bool *need_timer) |
|---|
| 4529 | 4609 | { |
|---|
| 4530 | 4610 | struct ipmi_recv_msg *msg; |
|---|
| 4531 | 4611 | |
|---|
| .. | .. |
|---|
| 4537 | 4617 | |
|---|
| 4538 | 4618 | if (timeout_period < ent->timeout) { |
|---|
| 4539 | 4619 | ent->timeout -= timeout_period; |
|---|
| 4540 | | - (*waiting_msgs)++; |
|---|
| 4620 | + *need_timer = true; |
|---|
| 4541 | 4621 | return; |
|---|
| 4542 | 4622 | } |
|---|
| 4543 | 4623 | |
|---|
| 4544 | 4624 | if (ent->retries_left == 0) { |
|---|
| 4545 | 4625 | /* The message has used all its retries. */ |
|---|
| 4546 | 4626 | ent->inuse = 0; |
|---|
| 4627 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 4547 | 4628 | msg = ent->recv_msg; |
|---|
| 4548 | 4629 | list_add_tail(&msg->link, timeouts); |
|---|
| 4549 | 4630 | if (ent->broadcast) |
|---|
| .. | .. |
|---|
| 4556 | 4637 | struct ipmi_smi_msg *smi_msg; |
|---|
| 4557 | 4638 | /* More retries, send again. */ |
|---|
| 4558 | 4639 | |
|---|
| 4559 | | - (*waiting_msgs)++; |
|---|
| 4640 | + *need_timer = true; |
|---|
| 4560 | 4641 | |
|---|
| 4561 | 4642 | /* |
|---|
| 4562 | 4643 | * Start with the max timer, set to normal timer after |
|---|
| .. | .. |
|---|
| 4601 | 4682 | } |
|---|
| 4602 | 4683 | } |
|---|
| 4603 | 4684 | |
|---|
| 4604 | | -static unsigned int ipmi_timeout_handler(struct ipmi_smi *intf, |
|---|
| 4605 | | - unsigned long timeout_period) |
|---|
| 4685 | +static bool ipmi_timeout_handler(struct ipmi_smi *intf, |
|---|
| 4686 | + unsigned long timeout_period) |
|---|
| 4606 | 4687 | { |
|---|
| 4607 | 4688 | struct list_head timeouts; |
|---|
| 4608 | 4689 | struct ipmi_recv_msg *msg, *msg2; |
|---|
| 4609 | 4690 | unsigned long flags; |
|---|
| 4610 | 4691 | int i; |
|---|
| 4611 | | - unsigned int waiting_msgs = 0; |
|---|
| 4692 | + bool need_timer = false; |
|---|
| 4612 | 4693 | |
|---|
| 4613 | 4694 | if (!intf->bmc_registered) { |
|---|
| 4614 | 4695 | kref_get(&intf->refcount); |
|---|
| 4615 | 4696 | if (!schedule_work(&intf->bmc_reg_work)) { |
|---|
| 4616 | 4697 | kref_put(&intf->refcount, intf_free); |
|---|
| 4617 | | - waiting_msgs++; |
|---|
| 4698 | + need_timer = true; |
|---|
| 4618 | 4699 | } |
|---|
| 4619 | 4700 | } |
|---|
| 4620 | 4701 | |
|---|
| .. | .. |
|---|
| 4634 | 4715 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) |
|---|
| 4635 | 4716 | check_msg_timeout(intf, &intf->seq_table[i], |
|---|
| 4636 | 4717 | &timeouts, timeout_period, i, |
|---|
| 4637 | | - &flags, &waiting_msgs); |
|---|
| 4718 | + &flags, &need_timer); |
|---|
| 4638 | 4719 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
|---|
| 4639 | 4720 | |
|---|
| 4640 | 4721 | list_for_each_entry_safe(msg, msg2, &timeouts, link) |
|---|
| .. | .. |
|---|
| 4665 | 4746 | |
|---|
| 4666 | 4747 | tasklet_schedule(&intf->recv_tasklet); |
|---|
| 4667 | 4748 | |
|---|
| 4668 | | - return waiting_msgs; |
|---|
| 4749 | + return need_timer; |
|---|
| 4669 | 4750 | } |
|---|
| 4670 | 4751 | |
|---|
| 4671 | 4752 | static void ipmi_request_event(struct ipmi_smi *intf) |
|---|
| .. | .. |
|---|
| 4685 | 4766 | static void ipmi_timeout(struct timer_list *unused) |
|---|
| 4686 | 4767 | { |
|---|
| 4687 | 4768 | struct ipmi_smi *intf; |
|---|
| 4688 | | - int nt = 0, index; |
|---|
| 4769 | + bool need_timer = false; |
|---|
| 4770 | + int index; |
|---|
| 4689 | 4771 | |
|---|
| 4690 | 4772 | if (atomic_read(&stop_operation)) |
|---|
| 4691 | 4773 | return; |
|---|
| 4692 | 4774 | |
|---|
| 4693 | 4775 | index = srcu_read_lock(&ipmi_interfaces_srcu); |
|---|
| 4694 | 4776 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
|---|
| 4695 | | - int lnt = 0; |
|---|
| 4696 | | - |
|---|
| 4697 | 4777 | if (atomic_read(&intf->event_waiters)) { |
|---|
| 4698 | 4778 | intf->ticks_to_req_ev--; |
|---|
| 4699 | 4779 | if (intf->ticks_to_req_ev == 0) { |
|---|
| 4700 | 4780 | ipmi_request_event(intf); |
|---|
| 4701 | 4781 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
|---|
| 4702 | 4782 | } |
|---|
| 4703 | | - lnt++; |
|---|
| 4783 | + need_timer = true; |
|---|
| 4704 | 4784 | } |
|---|
| 4705 | 4785 | |
|---|
| 4706 | | - lnt += ipmi_timeout_handler(intf, IPMI_TIMEOUT_TIME); |
|---|
| 4707 | | - |
|---|
| 4708 | | - lnt = !!lnt; |
|---|
| 4709 | | - if (lnt != intf->last_needs_timer && |
|---|
| 4710 | | - intf->handlers->set_need_watch) |
|---|
| 4711 | | - intf->handlers->set_need_watch(intf->send_info, lnt); |
|---|
| 4712 | | - intf->last_needs_timer = lnt; |
|---|
| 4713 | | - |
|---|
| 4714 | | - nt += lnt; |
|---|
| 4786 | + need_timer |= ipmi_timeout_handler(intf, IPMI_TIMEOUT_TIME); |
|---|
| 4715 | 4787 | } |
|---|
| 4716 | 4788 | srcu_read_unlock(&ipmi_interfaces_srcu, index); |
|---|
| 4717 | 4789 | |
|---|
| 4718 | | - if (nt) |
|---|
| 4790 | + if (need_timer) |
|---|
| 4719 | 4791 | mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); |
|---|
| 4720 | 4792 | } |
|---|
| 4721 | 4793 | |
|---|
| .. | .. |
|---|
| 4732 | 4804 | static void free_smi_msg(struct ipmi_smi_msg *msg) |
|---|
| 4733 | 4805 | { |
|---|
| 4734 | 4806 | atomic_dec(&smi_msg_inuse_count); |
|---|
| 4735 | | - kfree(msg); |
|---|
| 4807 | + /* Try to keep as much stuff out of the panic path as possible. */ |
|---|
| 4808 | + if (!oops_in_progress) |
|---|
| 4809 | + kfree(msg); |
|---|
| 4736 | 4810 | } |
|---|
| 4737 | 4811 | |
|---|
| 4738 | 4812 | struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) |
|---|
| .. | .. |
|---|
| 4751 | 4825 | static void free_recv_msg(struct ipmi_recv_msg *msg) |
|---|
| 4752 | 4826 | { |
|---|
| 4753 | 4827 | atomic_dec(&recv_msg_inuse_count); |
|---|
| 4754 | | - kfree(msg); |
|---|
| 4828 | + /* Try to keep as much stuff out of the panic path as possible. */ |
|---|
| 4829 | + if (!oops_in_progress) |
|---|
| 4830 | + kfree(msg); |
|---|
| 4755 | 4831 | } |
|---|
| 4756 | 4832 | |
|---|
| 4757 | 4833 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) |
|---|
| .. | .. |
|---|
| 4769 | 4845 | |
|---|
| 4770 | 4846 | void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) |
|---|
| 4771 | 4847 | { |
|---|
| 4772 | | - if (msg->user) |
|---|
| 4848 | + if (msg->user && !oops_in_progress) |
|---|
| 4773 | 4849 | kref_put(&msg->user->refcount, free_user); |
|---|
| 4774 | 4850 | msg->done(msg); |
|---|
| 4775 | 4851 | } |
|---|
| .. | .. |
|---|
| 5144 | 5220 | * avoids problems with race conditions removing the timer |
|---|
| 5145 | 5221 | * here. |
|---|
| 5146 | 5222 | */ |
|---|
| 5147 | | - atomic_inc(&stop_operation); |
|---|
| 5223 | + atomic_set(&stop_operation, 1); |
|---|
| 5148 | 5224 | del_timer_sync(&ipmi_timer); |
|---|
| 5149 | 5225 | |
|---|
| 5150 | 5226 | initialized = false; |
|---|
| .. | .. |
|---|
| 5152 | 5228 | /* Check for buffer leaks. */ |
|---|
| 5153 | 5229 | count = atomic_read(&smi_msg_inuse_count); |
|---|
| 5154 | 5230 | if (count != 0) |
|---|
| 5155 | | - pr_warn(PFX "SMI message count %d at exit\n", count); |
|---|
| 5231 | + pr_warn("SMI message count %d at exit\n", count); |
|---|
| 5156 | 5232 | count = atomic_read(&recv_msg_inuse_count); |
|---|
| 5157 | 5233 | if (count != 0) |
|---|
| 5158 | | - pr_warn(PFX "recv message count %d at exit\n", count); |
|---|
| 5234 | + pr_warn("recv message count %d at exit\n", count); |
|---|
| 5235 | + |
|---|
| 5159 | 5236 | cleanup_srcu_struct(&ipmi_interfaces_srcu); |
|---|
| 5160 | 5237 | } |
|---|
| 5161 | 5238 | if (drvregistered) |
|---|