| .. | .. |
|---|
| 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; |
|---|
| .. | .. |
|---|
| 1219 | 1284 | unsigned long flags; |
|---|
| 1220 | 1285 | struct cmd_rcvr *rcvr; |
|---|
| 1221 | 1286 | struct cmd_rcvr *rcvrs = NULL; |
|---|
| 1287 | + struct module *owner; |
|---|
| 1222 | 1288 | |
|---|
| 1223 | 1289 | if (!acquire_ipmi_user(user, &i)) { |
|---|
| 1224 | 1290 | /* |
|---|
| .. | .. |
|---|
| 1238 | 1304 | user->handler->shutdown(user->handler_data); |
|---|
| 1239 | 1305 | |
|---|
| 1240 | 1306 | if (user->handler->ipmi_watchdog_pretimeout) |
|---|
| 1241 | | - atomic_dec(&intf->event_waiters); |
|---|
| 1307 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_WATCHDOG); |
|---|
| 1242 | 1308 | |
|---|
| 1243 | 1309 | if (user->gets_events) |
|---|
| 1244 | 1310 | atomic_dec(&intf->event_waiters); |
|---|
| .. | .. |
|---|
| 1251 | 1317 | if (intf->seq_table[i].inuse |
|---|
| 1252 | 1318 | && (intf->seq_table[i].recv_msg->user == user)) { |
|---|
| 1253 | 1319 | intf->seq_table[i].inuse = 0; |
|---|
| 1320 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 1254 | 1321 | ipmi_free_recv_msg(intf->seq_table[i].recv_msg); |
|---|
| 1255 | 1322 | } |
|---|
| 1256 | 1323 | } |
|---|
| .. | .. |
|---|
| 1263 | 1330 | * synchronize_srcu()) then free everything in that list. |
|---|
| 1264 | 1331 | */ |
|---|
| 1265 | 1332 | mutex_lock(&intf->cmd_rcvrs_mutex); |
|---|
| 1266 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1333 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1334 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1267 | 1335 | if (rcvr->user == user) { |
|---|
| 1268 | 1336 | list_del_rcu(&rcvr->link); |
|---|
| 1269 | 1337 | rcvr->next = rcvrs; |
|---|
| .. | .. |
|---|
| 1278 | 1346 | kfree(rcvr); |
|---|
| 1279 | 1347 | } |
|---|
| 1280 | 1348 | |
|---|
| 1349 | + owner = intf->owner; |
|---|
| 1281 | 1350 | kref_put(&intf->refcount, intf_free); |
|---|
| 1282 | | - module_put(intf->owner); |
|---|
| 1351 | + module_put(owner); |
|---|
| 1283 | 1352 | } |
|---|
| 1284 | 1353 | |
|---|
| 1285 | 1354 | int ipmi_destroy_user(struct ipmi_user *user) |
|---|
| .. | .. |
|---|
| 1509 | 1578 | list_move_tail(&msg->link, &msgs); |
|---|
| 1510 | 1579 | intf->waiting_events_count = 0; |
|---|
| 1511 | 1580 | if (intf->event_msg_printed) { |
|---|
| 1512 | | - dev_warn(intf->si_dev, |
|---|
| 1513 | | - PFX "Event queue no longer full\n"); |
|---|
| 1581 | + dev_warn(intf->si_dev, "Event queue no longer full\n"); |
|---|
| 1514 | 1582 | intf->event_msg_printed = 0; |
|---|
| 1515 | 1583 | } |
|---|
| 1516 | 1584 | |
|---|
| .. | .. |
|---|
| 1542 | 1610 | { |
|---|
| 1543 | 1611 | struct cmd_rcvr *rcvr; |
|---|
| 1544 | 1612 | |
|---|
| 1545 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1613 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1614 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1546 | 1615 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) |
|---|
| 1547 | 1616 | && (rcvr->chans & (1 << chan))) |
|---|
| 1548 | 1617 | return rcvr; |
|---|
| .. | .. |
|---|
| 1557 | 1626 | { |
|---|
| 1558 | 1627 | struct cmd_rcvr *rcvr; |
|---|
| 1559 | 1628 | |
|---|
| 1560 | | - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { |
|---|
| 1629 | + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link, |
|---|
| 1630 | + lockdep_is_held(&intf->cmd_rcvrs_mutex)) { |
|---|
| 1561 | 1631 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) |
|---|
| 1562 | 1632 | && (rcvr->chans & chans)) |
|---|
| 1563 | 1633 | return 0; |
|---|
| .. | .. |
|---|
| 1595 | 1665 | goto out_unlock; |
|---|
| 1596 | 1666 | } |
|---|
| 1597 | 1667 | |
|---|
| 1598 | | - if (atomic_inc_return(&intf->event_waiters) == 1) |
|---|
| 1599 | | - need_waiter(intf); |
|---|
| 1668 | + smi_add_watch(intf, IPMI_WATCH_MASK_CHECK_COMMANDS); |
|---|
| 1600 | 1669 | |
|---|
| 1601 | 1670 | list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); |
|---|
| 1602 | 1671 | |
|---|
| .. | .. |
|---|
| 1646 | 1715 | synchronize_rcu(); |
|---|
| 1647 | 1716 | release_ipmi_user(user, index); |
|---|
| 1648 | 1717 | while (rcvrs) { |
|---|
| 1649 | | - atomic_dec(&intf->event_waiters); |
|---|
| 1718 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_COMMANDS); |
|---|
| 1650 | 1719 | rcvr = rcvrs; |
|---|
| 1651 | 1720 | rcvrs = rcvr->next; |
|---|
| 1652 | 1721 | kfree(rcvr); |
|---|
| .. | .. |
|---|
| 1763 | 1832 | return smi_msg; |
|---|
| 1764 | 1833 | } |
|---|
| 1765 | 1834 | |
|---|
| 1766 | | - |
|---|
| 1767 | 1835 | static void smi_send(struct ipmi_smi *intf, |
|---|
| 1768 | 1836 | const struct ipmi_smi_handlers *handlers, |
|---|
| 1769 | 1837 | struct ipmi_smi_msg *smi_msg, int priority) |
|---|
| 1770 | 1838 | { |
|---|
| 1771 | 1839 | int run_to_completion = intf->run_to_completion; |
|---|
| 1840 | + unsigned long flags = 0; |
|---|
| 1772 | 1841 | |
|---|
| 1773 | | - if (run_to_completion) { |
|---|
| 1774 | | - smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1775 | | - } else { |
|---|
| 1776 | | - unsigned long flags; |
|---|
| 1777 | | - |
|---|
| 1842 | + if (!run_to_completion) |
|---|
| 1778 | 1843 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); |
|---|
| 1779 | | - smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1844 | + smi_msg = smi_add_send_msg(intf, smi_msg, priority); |
|---|
| 1845 | + |
|---|
| 1846 | + if (!run_to_completion) |
|---|
| 1780 | 1847 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 1781 | | - } |
|---|
| 1782 | 1848 | |
|---|
| 1783 | 1849 | if (smi_msg) |
|---|
| 1784 | 1850 | handlers->sender(intf->send_info, smi_msg); |
|---|
| .. | .. |
|---|
| 2158 | 2224 | else { |
|---|
| 2159 | 2225 | smi_msg = ipmi_alloc_smi_msg(); |
|---|
| 2160 | 2226 | if (smi_msg == NULL) { |
|---|
| 2161 | | - ipmi_free_recv_msg(recv_msg); |
|---|
| 2227 | + if (!supplied_recv) |
|---|
| 2228 | + ipmi_free_recv_msg(recv_msg); |
|---|
| 2162 | 2229 | rv = -ENOMEM; |
|---|
| 2163 | 2230 | goto out; |
|---|
| 2164 | 2231 | } |
|---|
| .. | .. |
|---|
| 2202 | 2269 | ipmi_free_smi_msg(smi_msg); |
|---|
| 2203 | 2270 | ipmi_free_recv_msg(recv_msg); |
|---|
| 2204 | 2271 | } else { |
|---|
| 2205 | | - ipmi_debug_msg("Send", smi_msg->data, smi_msg->data_size); |
|---|
| 2272 | + pr_debug("Send: %*ph\n", smi_msg->data_size, smi_msg->data); |
|---|
| 2206 | 2273 | |
|---|
| 2207 | 2274 | smi_send(intf, intf->handlers, smi_msg, priority); |
|---|
| 2208 | 2275 | } |
|---|
| .. | .. |
|---|
| 2312 | 2379 | || (msg->msg.netfn != IPMI_NETFN_APP_RESPONSE) |
|---|
| 2313 | 2380 | || (msg->msg.cmd != IPMI_GET_DEVICE_ID_CMD)) { |
|---|
| 2314 | 2381 | 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); |
|---|
| 2382 | + "invalid device_id msg: addr_type=%d netfn=%x cmd=%x\n", |
|---|
| 2383 | + msg->addr.addr_type, msg->msg.netfn, msg->msg.cmd); |
|---|
| 2317 | 2384 | return; |
|---|
| 2318 | 2385 | } |
|---|
| 2319 | 2386 | |
|---|
| 2320 | 2387 | rv = ipmi_demangle_device_id(msg->msg.netfn, msg->msg.cmd, |
|---|
| 2321 | 2388 | msg->msg.data, msg->msg.data_len, &intf->bmc->fetch_id); |
|---|
| 2322 | 2389 | if (rv) { |
|---|
| 2323 | | - dev_warn(intf->si_dev, |
|---|
| 2324 | | - PFX "device id demangle failed: %d\n", rv); |
|---|
| 2390 | + dev_warn(intf->si_dev, "device id demangle failed: %d\n", rv); |
|---|
| 2391 | + /* record completion code when error */ |
|---|
| 2392 | + intf->bmc->cc = msg->msg.data[0]; |
|---|
| 2325 | 2393 | intf->bmc->dyn_id_set = 0; |
|---|
| 2326 | 2394 | } else { |
|---|
| 2327 | 2395 | /* |
|---|
| .. | .. |
|---|
| 2367 | 2435 | static int __get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc) |
|---|
| 2368 | 2436 | { |
|---|
| 2369 | 2437 | int rv; |
|---|
| 2370 | | - |
|---|
| 2371 | | - bmc->dyn_id_set = 2; |
|---|
| 2438 | + unsigned int retry_count = 0; |
|---|
| 2372 | 2439 | |
|---|
| 2373 | 2440 | intf->null_user_handler = bmc_device_id_handler; |
|---|
| 2374 | 2441 | |
|---|
| 2442 | +retry: |
|---|
| 2443 | + bmc->cc = 0; |
|---|
| 2444 | + bmc->dyn_id_set = 2; |
|---|
| 2445 | + |
|---|
| 2375 | 2446 | rv = send_get_device_id_cmd(intf); |
|---|
| 2376 | 2447 | if (rv) |
|---|
| 2377 | | - return rv; |
|---|
| 2448 | + goto out_reset_handler; |
|---|
| 2378 | 2449 | |
|---|
| 2379 | 2450 | wait_event(intf->waitq, bmc->dyn_id_set != 2); |
|---|
| 2380 | 2451 | |
|---|
| 2381 | | - if (!bmc->dyn_id_set) |
|---|
| 2452 | + if (!bmc->dyn_id_set) { |
|---|
| 2453 | + if ((bmc->cc == IPMI_DEVICE_IN_FW_UPDATE_ERR |
|---|
| 2454 | + || bmc->cc == IPMI_DEVICE_IN_INIT_ERR |
|---|
| 2455 | + || bmc->cc == IPMI_NOT_IN_MY_STATE_ERR) |
|---|
| 2456 | + && ++retry_count <= GET_DEVICE_ID_MAX_RETRY) { |
|---|
| 2457 | + msleep(500); |
|---|
| 2458 | + dev_warn(intf->si_dev, |
|---|
| 2459 | + "BMC returned 0x%2.2x, retry get bmc device id\n", |
|---|
| 2460 | + bmc->cc); |
|---|
| 2461 | + goto retry; |
|---|
| 2462 | + } |
|---|
| 2463 | + |
|---|
| 2382 | 2464 | rv = -EIO; /* Something went wrong in the fetch. */ |
|---|
| 2465 | + } |
|---|
| 2383 | 2466 | |
|---|
| 2384 | 2467 | /* dyn_id_set makes the id data available. */ |
|---|
| 2385 | 2468 | smp_rmb(); |
|---|
| 2386 | 2469 | |
|---|
| 2470 | +out_reset_handler: |
|---|
| 2387 | 2471 | intf->null_user_handler = NULL; |
|---|
| 2388 | 2472 | |
|---|
| 2389 | 2473 | return rv; |
|---|
| .. | .. |
|---|
| 2703 | 2787 | if (!guid_set) |
|---|
| 2704 | 2788 | return -ENOENT; |
|---|
| 2705 | 2789 | |
|---|
| 2706 | | - return snprintf(buf, 38, "%pUl\n", guid.b); |
|---|
| 2790 | + return snprintf(buf, UUID_STRING_LEN + 1 + 1, "%pUl\n", &guid); |
|---|
| 2707 | 2791 | } |
|---|
| 2708 | 2792 | static DEVICE_ATTR_RO(guid); |
|---|
| 2709 | 2793 | |
|---|
| .. | .. |
|---|
| 2758 | 2842 | .groups = bmc_dev_attr_groups, |
|---|
| 2759 | 2843 | }; |
|---|
| 2760 | 2844 | |
|---|
| 2761 | | -static int __find_bmc_guid(struct device *dev, void *data) |
|---|
| 2845 | +static int __find_bmc_guid(struct device *dev, const void *data) |
|---|
| 2762 | 2846 | { |
|---|
| 2763 | | - guid_t *guid = data; |
|---|
| 2847 | + const guid_t *guid = data; |
|---|
| 2764 | 2848 | struct bmc_device *bmc; |
|---|
| 2765 | 2849 | int rv; |
|---|
| 2766 | 2850 | |
|---|
| .. | .. |
|---|
| 2796 | 2880 | unsigned char device_id; |
|---|
| 2797 | 2881 | }; |
|---|
| 2798 | 2882 | |
|---|
| 2799 | | -static int __find_bmc_prod_dev_id(struct device *dev, void *data) |
|---|
| 2883 | +static int __find_bmc_prod_dev_id(struct device *dev, const void *data) |
|---|
| 2800 | 2884 | { |
|---|
| 2801 | | - struct prod_dev_id *cid = data; |
|---|
| 2885 | + const struct prod_dev_id *cid = data; |
|---|
| 2802 | 2886 | struct bmc_device *bmc; |
|---|
| 2803 | 2887 | int rv; |
|---|
| 2804 | 2888 | |
|---|
| .. | .. |
|---|
| 2944 | 3028 | mutex_unlock(&bmc->dyn_mutex); |
|---|
| 2945 | 3029 | |
|---|
| 2946 | 3030 | 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", |
|---|
| 3031 | + "interfacing existing BMC (man_id: 0x%6.6x, prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", |
|---|
| 2949 | 3032 | bmc->id.manufacturer_id, |
|---|
| 2950 | 3033 | bmc->id.product_id, |
|---|
| 2951 | 3034 | bmc->id.device_id); |
|---|
| .. | .. |
|---|
| 2987 | 3070 | rv = platform_device_register(&bmc->pdev); |
|---|
| 2988 | 3071 | if (rv) { |
|---|
| 2989 | 3072 | dev_err(intf->si_dev, |
|---|
| 2990 | | - PFX " Unable to register bmc device: %d\n", |
|---|
| 3073 | + "Unable to register bmc device: %d\n", |
|---|
| 2991 | 3074 | rv); |
|---|
| 2992 | 3075 | goto out_list_del; |
|---|
| 2993 | 3076 | } |
|---|
| .. | .. |
|---|
| 3005 | 3088 | */ |
|---|
| 3006 | 3089 | rv = sysfs_create_link(&intf->si_dev->kobj, &bmc->pdev.dev.kobj, "bmc"); |
|---|
| 3007 | 3090 | if (rv) { |
|---|
| 3008 | | - dev_err(intf->si_dev, |
|---|
| 3009 | | - PFX "Unable to create bmc symlink: %d\n", rv); |
|---|
| 3091 | + dev_err(intf->si_dev, "Unable to create bmc symlink: %d\n", rv); |
|---|
| 3010 | 3092 | goto out_put_bmc; |
|---|
| 3011 | 3093 | } |
|---|
| 3012 | 3094 | |
|---|
| .. | .. |
|---|
| 3015 | 3097 | intf->my_dev_name = kasprintf(GFP_KERNEL, "ipmi%d", intf_num); |
|---|
| 3016 | 3098 | if (!intf->my_dev_name) { |
|---|
| 3017 | 3099 | rv = -ENOMEM; |
|---|
| 3018 | | - dev_err(intf->si_dev, |
|---|
| 3019 | | - PFX "Unable to allocate link from BMC: %d\n", rv); |
|---|
| 3100 | + dev_err(intf->si_dev, "Unable to allocate link from BMC: %d\n", |
|---|
| 3101 | + rv); |
|---|
| 3020 | 3102 | goto out_unlink1; |
|---|
| 3021 | 3103 | } |
|---|
| 3022 | 3104 | |
|---|
| 3023 | 3105 | rv = sysfs_create_link(&bmc->pdev.dev.kobj, &intf->si_dev->kobj, |
|---|
| 3024 | 3106 | intf->my_dev_name); |
|---|
| 3025 | 3107 | 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); |
|---|
| 3108 | + dev_err(intf->si_dev, "Unable to create symlink to bmc: %d\n", |
|---|
| 3109 | + rv); |
|---|
| 3030 | 3110 | goto out_free_my_dev_name; |
|---|
| 3031 | 3111 | } |
|---|
| 3032 | 3112 | |
|---|
| .. | .. |
|---|
| 3107 | 3187 | goto out; |
|---|
| 3108 | 3188 | } |
|---|
| 3109 | 3189 | |
|---|
| 3110 | | - if (msg->msg.data_len < 17) { |
|---|
| 3190 | + if (msg->msg.data_len < UUID_SIZE + 1) { |
|---|
| 3111 | 3191 | bmc->dyn_guid_set = 0; |
|---|
| 3112 | 3192 | 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); |
|---|
| 3193 | + "The GUID response from the BMC was too short, it was %d but should have been %d. Assuming GUID is not available.\n", |
|---|
| 3194 | + msg->msg.data_len, UUID_SIZE + 1); |
|---|
| 3115 | 3195 | goto out; |
|---|
| 3116 | 3196 | } |
|---|
| 3117 | 3197 | |
|---|
| 3118 | | - memcpy(bmc->fetch_guid.b, msg->msg.data + 1, 16); |
|---|
| 3198 | + import_guid(&bmc->fetch_guid, msg->msg.data + 1); |
|---|
| 3119 | 3199 | /* |
|---|
| 3120 | 3200 | * Make sure the guid data is available before setting |
|---|
| 3121 | 3201 | * dyn_guid_set. |
|---|
| .. | .. |
|---|
| 3190 | 3270 | /* It's the one we want */ |
|---|
| 3191 | 3271 | if (msg->msg.data[0] != 0) { |
|---|
| 3192 | 3272 | /* Got an error from the channel, just go on. */ |
|---|
| 3193 | | - |
|---|
| 3194 | 3273 | if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { |
|---|
| 3195 | 3274 | /* |
|---|
| 3196 | 3275 | * If the MC does not support this |
|---|
| .. | .. |
|---|
| 3234 | 3313 | if (rv) { |
|---|
| 3235 | 3314 | /* Got an error somehow, just give up. */ |
|---|
| 3236 | 3315 | dev_warn(intf->si_dev, |
|---|
| 3237 | | - PFX "Error sending channel information for channel %d: %d\n", |
|---|
| 3316 | + "Error sending channel information for channel %d: %d\n", |
|---|
| 3238 | 3317 | intf->curr_channel, rv); |
|---|
| 3239 | 3318 | |
|---|
| 3240 | 3319 | intf->channel_list = intf->wchannels + set; |
|---|
| .. | .. |
|---|
| 3274 | 3353 | dev_warn(intf->si_dev, |
|---|
| 3275 | 3354 | "Error sending channel information for channel 0, %d\n", |
|---|
| 3276 | 3355 | rv); |
|---|
| 3356 | + intf->null_user_handler = NULL; |
|---|
| 3277 | 3357 | return -EIO; |
|---|
| 3278 | 3358 | } |
|---|
| 3279 | 3359 | |
|---|
| .. | .. |
|---|
| 3375 | 3455 | intf->curr_seq = 0; |
|---|
| 3376 | 3456 | spin_lock_init(&intf->waiting_rcv_msgs_lock); |
|---|
| 3377 | 3457 | INIT_LIST_HEAD(&intf->waiting_rcv_msgs); |
|---|
| 3378 | | - tasklet_init(&intf->recv_tasklet, |
|---|
| 3379 | | - smi_recv_tasklet, |
|---|
| 3380 | | - (unsigned long) intf); |
|---|
| 3458 | + tasklet_setup(&intf->recv_tasklet, |
|---|
| 3459 | + smi_recv_tasklet); |
|---|
| 3381 | 3460 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); |
|---|
| 3382 | 3461 | spin_lock_init(&intf->xmit_msgs_lock); |
|---|
| 3383 | 3462 | INIT_LIST_HEAD(&intf->xmit_msgs); |
|---|
| 3384 | 3463 | INIT_LIST_HEAD(&intf->hp_xmit_msgs); |
|---|
| 3385 | 3464 | spin_lock_init(&intf->events_lock); |
|---|
| 3465 | + spin_lock_init(&intf->watch_lock); |
|---|
| 3386 | 3466 | atomic_set(&intf->event_waiters, 0); |
|---|
| 3387 | 3467 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
|---|
| 3388 | 3468 | INIT_LIST_HEAD(&intf->waiting_events); |
|---|
| .. | .. |
|---|
| 3398 | 3478 | /* Look for a hole in the numbers. */ |
|---|
| 3399 | 3479 | i = 0; |
|---|
| 3400 | 3480 | link = &ipmi_interfaces; |
|---|
| 3401 | | - list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) { |
|---|
| 3481 | + list_for_each_entry_rcu(tintf, &ipmi_interfaces, link, |
|---|
| 3482 | + ipmi_interfaces_mutex_held()) { |
|---|
| 3402 | 3483 | if (tintf->intf_num != i) { |
|---|
| 3403 | 3484 | link = &tintf->link; |
|---|
| 3404 | 3485 | break; |
|---|
| .. | .. |
|---|
| 3461 | 3542 | struct ipmi_smi_msg *msg, |
|---|
| 3462 | 3543 | unsigned char err) |
|---|
| 3463 | 3544 | { |
|---|
| 3545 | + int rv; |
|---|
| 3464 | 3546 | msg->rsp[0] = msg->data[0] | 4; |
|---|
| 3465 | 3547 | msg->rsp[1] = msg->data[1]; |
|---|
| 3466 | 3548 | msg->rsp[2] = err; |
|---|
| 3467 | 3549 | msg->rsp_size = 3; |
|---|
| 3468 | | - /* It's an error, so it will never requeue, no need to check return. */ |
|---|
| 3469 | | - handle_one_recv_msg(intf, msg); |
|---|
| 3550 | + |
|---|
| 3551 | + /* This will never requeue, but it may ask us to free the message. */ |
|---|
| 3552 | + rv = handle_one_recv_msg(intf, msg); |
|---|
| 3553 | + if (rv == 0) |
|---|
| 3554 | + ipmi_free_smi_msg(msg); |
|---|
| 3470 | 3555 | } |
|---|
| 3471 | 3556 | |
|---|
| 3472 | 3557 | static void cleanup_smi_msgs(struct ipmi_smi *intf) |
|---|
| .. | .. |
|---|
| 3671 | 3756 | msg->data[10] = ipmb_checksum(&msg->data[6], 4); |
|---|
| 3672 | 3757 | msg->data_size = 11; |
|---|
| 3673 | 3758 | |
|---|
| 3674 | | - ipmi_debug_msg("Invalid command:", msg->data, msg->data_size); |
|---|
| 3759 | + pr_debug("Invalid command: %*ph\n", msg->data_size, msg->data); |
|---|
| 3675 | 3760 | |
|---|
| 3676 | 3761 | rcu_read_lock(); |
|---|
| 3677 | 3762 | if (!intf->in_shutdown) { |
|---|
| .. | .. |
|---|
| 4107 | 4192 | * message. |
|---|
| 4108 | 4193 | */ |
|---|
| 4109 | 4194 | dev_warn(intf->si_dev, |
|---|
| 4110 | | - PFX "Event queue full, discarding incoming events\n"); |
|---|
| 4195 | + "Event queue full, discarding incoming events\n"); |
|---|
| 4111 | 4196 | intf->event_msg_printed = 1; |
|---|
| 4112 | 4197 | } |
|---|
| 4113 | 4198 | |
|---|
| .. | .. |
|---|
| 4126 | 4211 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
|---|
| 4127 | 4212 | if (recv_msg == NULL) { |
|---|
| 4128 | 4213 | 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"); |
|---|
| 4214 | + "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 | 4215 | return 0; |
|---|
| 4131 | 4216 | } |
|---|
| 4132 | 4217 | |
|---|
| .. | .. |
|---|
| 4158 | 4243 | int requeue; |
|---|
| 4159 | 4244 | int chan; |
|---|
| 4160 | 4245 | |
|---|
| 4161 | | - ipmi_debug_msg("Recv:", msg->rsp, msg->rsp_size); |
|---|
| 4162 | | - if (msg->rsp_size < 2) { |
|---|
| 4246 | + pr_debug("Recv: %*ph\n", msg->rsp_size, msg->rsp); |
|---|
| 4247 | + |
|---|
| 4248 | + if ((msg->data_size >= 2) |
|---|
| 4249 | + && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
|---|
| 4250 | + && (msg->data[1] == IPMI_SEND_MSG_CMD) |
|---|
| 4251 | + && (msg->user_data == NULL)) { |
|---|
| 4252 | + |
|---|
| 4253 | + if (intf->in_shutdown) |
|---|
| 4254 | + goto free_msg; |
|---|
| 4255 | + |
|---|
| 4256 | + /* |
|---|
| 4257 | + * This is the local response to a command send, start |
|---|
| 4258 | + * the timer for these. The user_data will not be |
|---|
| 4259 | + * NULL if this is a response send, and we will let |
|---|
| 4260 | + * response sends just go through. |
|---|
| 4261 | + */ |
|---|
| 4262 | + |
|---|
| 4263 | + /* |
|---|
| 4264 | + * Check for errors, if we get certain errors (ones |
|---|
| 4265 | + * that mean basically we can try again later), we |
|---|
| 4266 | + * ignore them and start the timer. Otherwise we |
|---|
| 4267 | + * report the error immediately. |
|---|
| 4268 | + */ |
|---|
| 4269 | + if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) |
|---|
| 4270 | + && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) |
|---|
| 4271 | + && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) |
|---|
| 4272 | + && (msg->rsp[2] != IPMI_BUS_ERR) |
|---|
| 4273 | + && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { |
|---|
| 4274 | + int ch = msg->rsp[3] & 0xf; |
|---|
| 4275 | + struct ipmi_channel *chans; |
|---|
| 4276 | + |
|---|
| 4277 | + /* Got an error sending the message, handle it. */ |
|---|
| 4278 | + |
|---|
| 4279 | + chans = READ_ONCE(intf->channel_list)->c; |
|---|
| 4280 | + if ((chans[ch].medium == IPMI_CHANNEL_MEDIUM_8023LAN) |
|---|
| 4281 | + || (chans[ch].medium == IPMI_CHANNEL_MEDIUM_ASYNC)) |
|---|
| 4282 | + ipmi_inc_stat(intf, sent_lan_command_errs); |
|---|
| 4283 | + else |
|---|
| 4284 | + ipmi_inc_stat(intf, sent_ipmb_command_errs); |
|---|
| 4285 | + intf_err_seq(intf, msg->msgid, msg->rsp[2]); |
|---|
| 4286 | + } else |
|---|
| 4287 | + /* The message was sent, start the timer. */ |
|---|
| 4288 | + intf_start_seq_timer(intf, msg->msgid); |
|---|
| 4289 | +free_msg: |
|---|
| 4290 | + requeue = 0; |
|---|
| 4291 | + goto out; |
|---|
| 4292 | + |
|---|
| 4293 | + } else if (msg->rsp_size < 2) { |
|---|
| 4163 | 4294 | /* Message is too small to be correct. */ |
|---|
| 4164 | 4295 | dev_warn(intf->si_dev, |
|---|
| 4165 | | - PFX "BMC returned to small a message for netfn %x cmd %x, got %d bytes\n", |
|---|
| 4296 | + "BMC returned too small a message for netfn %x cmd %x, got %d bytes\n", |
|---|
| 4166 | 4297 | (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size); |
|---|
| 4167 | 4298 | |
|---|
| 4168 | 4299 | /* Generate an error response for the message. */ |
|---|
| .. | .. |
|---|
| 4177 | 4308 | * marginally correct. |
|---|
| 4178 | 4309 | */ |
|---|
| 4179 | 4310 | dev_warn(intf->si_dev, |
|---|
| 4180 | | - PFX "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", |
|---|
| 4311 | + "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", |
|---|
| 4181 | 4312 | (msg->data[0] >> 2) | 1, msg->data[1], |
|---|
| 4182 | 4313 | msg->rsp[0] >> 2, msg->rsp[1]); |
|---|
| 4183 | 4314 | |
|---|
| .. | .. |
|---|
| 4364 | 4495 | } |
|---|
| 4365 | 4496 | } |
|---|
| 4366 | 4497 | |
|---|
| 4367 | | -static void smi_recv_tasklet(unsigned long val) |
|---|
| 4498 | +static void smi_recv_tasklet(struct tasklet_struct *t) |
|---|
| 4368 | 4499 | { |
|---|
| 4369 | 4500 | unsigned long flags = 0; /* keep us warning-free. */ |
|---|
| 4370 | | - struct ipmi_smi *intf = (struct ipmi_smi *) val; |
|---|
| 4501 | + struct ipmi_smi *intf = from_tasklet(intf, t, recv_tasklet); |
|---|
| 4371 | 4502 | int run_to_completion = intf->run_to_completion; |
|---|
| 4372 | 4503 | struct ipmi_smi_msg *newmsg = NULL; |
|---|
| 4373 | 4504 | |
|---|
| .. | .. |
|---|
| 4398 | 4529 | intf->curr_msg = newmsg; |
|---|
| 4399 | 4530 | } |
|---|
| 4400 | 4531 | } |
|---|
| 4532 | + |
|---|
| 4401 | 4533 | if (!run_to_completion) |
|---|
| 4402 | 4534 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 4403 | 4535 | if (newmsg) |
|---|
| .. | .. |
|---|
| 4415 | 4547 | unsigned long flags = 0; /* keep us warning-free. */ |
|---|
| 4416 | 4548 | int run_to_completion = intf->run_to_completion; |
|---|
| 4417 | 4549 | |
|---|
| 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 | | - } |
|---|
| 4550 | + /* |
|---|
| 4551 | + * To preserve message order, we keep a queue and deliver from |
|---|
| 4552 | + * a tasklet. |
|---|
| 4553 | + */ |
|---|
| 4554 | + if (!run_to_completion) |
|---|
| 4555 | + spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); |
|---|
| 4556 | + list_add_tail(&msg->link, &intf->waiting_rcv_msgs); |
|---|
| 4557 | + if (!run_to_completion) |
|---|
| 4558 | + spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, |
|---|
| 4559 | + flags); |
|---|
| 4474 | 4560 | |
|---|
| 4475 | 4561 | if (!run_to_completion) |
|---|
| 4476 | 4562 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); |
|---|
| .. | .. |
|---|
| 4484 | 4570 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
|---|
| 4485 | 4571 | |
|---|
| 4486 | 4572 | if (run_to_completion) |
|---|
| 4487 | | - smi_recv_tasklet((unsigned long) intf); |
|---|
| 4573 | + smi_recv_tasklet(&intf->recv_tasklet); |
|---|
| 4488 | 4574 | else |
|---|
| 4489 | 4575 | tasklet_schedule(&intf->recv_tasklet); |
|---|
| 4490 | 4576 | } |
|---|
| .. | .. |
|---|
| 4516 | 4602 | smi_msg->data_size = recv_msg->msg.data_len; |
|---|
| 4517 | 4603 | smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); |
|---|
| 4518 | 4604 | |
|---|
| 4519 | | - ipmi_debug_msg("Resend: ", smi_msg->data, smi_msg->data_size); |
|---|
| 4605 | + pr_debug("Resend: %*ph\n", smi_msg->data_size, smi_msg->data); |
|---|
| 4520 | 4606 | |
|---|
| 4521 | 4607 | return smi_msg; |
|---|
| 4522 | 4608 | } |
|---|
| .. | .. |
|---|
| 4525 | 4611 | struct list_head *timeouts, |
|---|
| 4526 | 4612 | unsigned long timeout_period, |
|---|
| 4527 | 4613 | int slot, unsigned long *flags, |
|---|
| 4528 | | - unsigned int *waiting_msgs) |
|---|
| 4614 | + bool *need_timer) |
|---|
| 4529 | 4615 | { |
|---|
| 4530 | 4616 | struct ipmi_recv_msg *msg; |
|---|
| 4531 | 4617 | |
|---|
| .. | .. |
|---|
| 4537 | 4623 | |
|---|
| 4538 | 4624 | if (timeout_period < ent->timeout) { |
|---|
| 4539 | 4625 | ent->timeout -= timeout_period; |
|---|
| 4540 | | - (*waiting_msgs)++; |
|---|
| 4626 | + *need_timer = true; |
|---|
| 4541 | 4627 | return; |
|---|
| 4542 | 4628 | } |
|---|
| 4543 | 4629 | |
|---|
| 4544 | 4630 | if (ent->retries_left == 0) { |
|---|
| 4545 | 4631 | /* The message has used all its retries. */ |
|---|
| 4546 | 4632 | ent->inuse = 0; |
|---|
| 4633 | + smi_remove_watch(intf, IPMI_WATCH_MASK_CHECK_MESSAGES); |
|---|
| 4547 | 4634 | msg = ent->recv_msg; |
|---|
| 4548 | 4635 | list_add_tail(&msg->link, timeouts); |
|---|
| 4549 | 4636 | if (ent->broadcast) |
|---|
| .. | .. |
|---|
| 4556 | 4643 | struct ipmi_smi_msg *smi_msg; |
|---|
| 4557 | 4644 | /* More retries, send again. */ |
|---|
| 4558 | 4645 | |
|---|
| 4559 | | - (*waiting_msgs)++; |
|---|
| 4646 | + *need_timer = true; |
|---|
| 4560 | 4647 | |
|---|
| 4561 | 4648 | /* |
|---|
| 4562 | 4649 | * Start with the max timer, set to normal timer after |
|---|
| .. | .. |
|---|
| 4601 | 4688 | } |
|---|
| 4602 | 4689 | } |
|---|
| 4603 | 4690 | |
|---|
| 4604 | | -static unsigned int ipmi_timeout_handler(struct ipmi_smi *intf, |
|---|
| 4605 | | - unsigned long timeout_period) |
|---|
| 4691 | +static bool ipmi_timeout_handler(struct ipmi_smi *intf, |
|---|
| 4692 | + unsigned long timeout_period) |
|---|
| 4606 | 4693 | { |
|---|
| 4607 | 4694 | struct list_head timeouts; |
|---|
| 4608 | 4695 | struct ipmi_recv_msg *msg, *msg2; |
|---|
| 4609 | 4696 | unsigned long flags; |
|---|
| 4610 | 4697 | int i; |
|---|
| 4611 | | - unsigned int waiting_msgs = 0; |
|---|
| 4698 | + bool need_timer = false; |
|---|
| 4612 | 4699 | |
|---|
| 4613 | 4700 | if (!intf->bmc_registered) { |
|---|
| 4614 | 4701 | kref_get(&intf->refcount); |
|---|
| 4615 | 4702 | if (!schedule_work(&intf->bmc_reg_work)) { |
|---|
| 4616 | 4703 | kref_put(&intf->refcount, intf_free); |
|---|
| 4617 | | - waiting_msgs++; |
|---|
| 4704 | + need_timer = true; |
|---|
| 4618 | 4705 | } |
|---|
| 4619 | 4706 | } |
|---|
| 4620 | 4707 | |
|---|
| .. | .. |
|---|
| 4634 | 4721 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) |
|---|
| 4635 | 4722 | check_msg_timeout(intf, &intf->seq_table[i], |
|---|
| 4636 | 4723 | &timeouts, timeout_period, i, |
|---|
| 4637 | | - &flags, &waiting_msgs); |
|---|
| 4724 | + &flags, &need_timer); |
|---|
| 4638 | 4725 | spin_unlock_irqrestore(&intf->seq_lock, flags); |
|---|
| 4639 | 4726 | |
|---|
| 4640 | 4727 | list_for_each_entry_safe(msg, msg2, &timeouts, link) |
|---|
| .. | .. |
|---|
| 4665 | 4752 | |
|---|
| 4666 | 4753 | tasklet_schedule(&intf->recv_tasklet); |
|---|
| 4667 | 4754 | |
|---|
| 4668 | | - return waiting_msgs; |
|---|
| 4755 | + return need_timer; |
|---|
| 4669 | 4756 | } |
|---|
| 4670 | 4757 | |
|---|
| 4671 | 4758 | static void ipmi_request_event(struct ipmi_smi *intf) |
|---|
| .. | .. |
|---|
| 4685 | 4772 | static void ipmi_timeout(struct timer_list *unused) |
|---|
| 4686 | 4773 | { |
|---|
| 4687 | 4774 | struct ipmi_smi *intf; |
|---|
| 4688 | | - int nt = 0, index; |
|---|
| 4775 | + bool need_timer = false; |
|---|
| 4776 | + int index; |
|---|
| 4689 | 4777 | |
|---|
| 4690 | 4778 | if (atomic_read(&stop_operation)) |
|---|
| 4691 | 4779 | return; |
|---|
| 4692 | 4780 | |
|---|
| 4693 | 4781 | index = srcu_read_lock(&ipmi_interfaces_srcu); |
|---|
| 4694 | 4782 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
|---|
| 4695 | | - int lnt = 0; |
|---|
| 4696 | | - |
|---|
| 4697 | 4783 | if (atomic_read(&intf->event_waiters)) { |
|---|
| 4698 | 4784 | intf->ticks_to_req_ev--; |
|---|
| 4699 | 4785 | if (intf->ticks_to_req_ev == 0) { |
|---|
| 4700 | 4786 | ipmi_request_event(intf); |
|---|
| 4701 | 4787 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
|---|
| 4702 | 4788 | } |
|---|
| 4703 | | - lnt++; |
|---|
| 4789 | + need_timer = true; |
|---|
| 4704 | 4790 | } |
|---|
| 4705 | 4791 | |
|---|
| 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; |
|---|
| 4792 | + need_timer |= ipmi_timeout_handler(intf, IPMI_TIMEOUT_TIME); |
|---|
| 4715 | 4793 | } |
|---|
| 4716 | 4794 | srcu_read_unlock(&ipmi_interfaces_srcu, index); |
|---|
| 4717 | 4795 | |
|---|
| 4718 | | - if (nt) |
|---|
| 4796 | + if (need_timer) |
|---|
| 4719 | 4797 | mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); |
|---|
| 4720 | 4798 | } |
|---|
| 4721 | 4799 | |
|---|
| .. | .. |
|---|
| 4732 | 4810 | static void free_smi_msg(struct ipmi_smi_msg *msg) |
|---|
| 4733 | 4811 | { |
|---|
| 4734 | 4812 | atomic_dec(&smi_msg_inuse_count); |
|---|
| 4735 | | - kfree(msg); |
|---|
| 4813 | + /* Try to keep as much stuff out of the panic path as possible. */ |
|---|
| 4814 | + if (!oops_in_progress) |
|---|
| 4815 | + kfree(msg); |
|---|
| 4736 | 4816 | } |
|---|
| 4737 | 4817 | |
|---|
| 4738 | 4818 | struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) |
|---|
| .. | .. |
|---|
| 4751 | 4831 | static void free_recv_msg(struct ipmi_recv_msg *msg) |
|---|
| 4752 | 4832 | { |
|---|
| 4753 | 4833 | atomic_dec(&recv_msg_inuse_count); |
|---|
| 4754 | | - kfree(msg); |
|---|
| 4834 | + /* Try to keep as much stuff out of the panic path as possible. */ |
|---|
| 4835 | + if (!oops_in_progress) |
|---|
| 4836 | + kfree(msg); |
|---|
| 4755 | 4837 | } |
|---|
| 4756 | 4838 | |
|---|
| 4757 | 4839 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) |
|---|
| .. | .. |
|---|
| 4769 | 4851 | |
|---|
| 4770 | 4852 | void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) |
|---|
| 4771 | 4853 | { |
|---|
| 4772 | | - if (msg->user) |
|---|
| 4854 | + if (msg->user && !oops_in_progress) |
|---|
| 4773 | 4855 | kref_put(&msg->user->refcount, free_user); |
|---|
| 4774 | 4856 | msg->done(msg); |
|---|
| 4775 | 4857 | } |
|---|
| .. | .. |
|---|
| 5144 | 5226 | * avoids problems with race conditions removing the timer |
|---|
| 5145 | 5227 | * here. |
|---|
| 5146 | 5228 | */ |
|---|
| 5147 | | - atomic_inc(&stop_operation); |
|---|
| 5229 | + atomic_set(&stop_operation, 1); |
|---|
| 5148 | 5230 | del_timer_sync(&ipmi_timer); |
|---|
| 5149 | 5231 | |
|---|
| 5150 | 5232 | initialized = false; |
|---|
| .. | .. |
|---|
| 5152 | 5234 | /* Check for buffer leaks. */ |
|---|
| 5153 | 5235 | count = atomic_read(&smi_msg_inuse_count); |
|---|
| 5154 | 5236 | if (count != 0) |
|---|
| 5155 | | - pr_warn(PFX "SMI message count %d at exit\n", count); |
|---|
| 5237 | + pr_warn("SMI message count %d at exit\n", count); |
|---|
| 5156 | 5238 | count = atomic_read(&recv_msg_inuse_count); |
|---|
| 5157 | 5239 | if (count != 0) |
|---|
| 5158 | | - pr_warn(PFX "recv message count %d at exit\n", count); |
|---|
| 5240 | + pr_warn("recv message count %d at exit\n", count); |
|---|
| 5241 | + |
|---|
| 5159 | 5242 | cleanup_srcu_struct(&ipmi_interfaces_srcu); |
|---|
| 5160 | 5243 | } |
|---|
| 5161 | 5244 | if (drvregistered) |
|---|