.. | .. |
---|
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) |
---|