The further approach, add a cleanup interface in sysfs. The administrator write '1' to clean_msg, and ipmi clear the entire message queue.
Signed-off-by: Chen Guanqiao <chen.chencha...@foxmail.com> --- drivers/char/ipmi/ipmi_msghandler.c | 82 +++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0238be81c435..29d6779a569f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -46,6 +46,9 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf); static void need_waiter(struct ipmi_smi *intf); static int handle_one_recv_msg(struct ipmi_smi *intf, struct ipmi_smi_msg *msg); +static void deliver_smi_err_response(struct ipmi_smi *intf, + struct ipmi_smi_msg *msg, + unsigned char err); static bool initialized; static bool drvregistered; @@ -2761,6 +2764,71 @@ static void get_msg_count(unsigned int *hp_count, unsigned int *count) *count = hp_msg_count; } +static void __cleanup_msgs_queue(struct ipmi_smi *intf) +{ + int i; + unsigned long flags; + int run_to_completion = intf->run_to_completion; + + rcu_read_lock(); + if (!run_to_completion) + spin_lock_irqsave(&intf->xmit_msgs_lock, flags); + if (!intf->in_shutdown) { + struct ipmi_smi_msg *msg; + struct list_head *entry = NULL; + + while (!list_empty(&intf->xmit_msgs)) { + if (!list_empty(&intf->hp_xmit_msgs)) + entry = intf->hp_xmit_msgs.next; + else if (!list_empty(&intf->xmit_msgs)) + entry = intf->xmit_msgs.next; + + if (!entry) + continue; + + list_del(entry); + msg = list_entry(entry, struct ipmi_smi_msg, link); + deliver_smi_err_response(intf, msg, + IPMI_ERR_UNSPECIFIED); + } + } + if (!run_to_completion) + spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); + rcu_read_unlock(); + + spin_lock_irqsave(&intf->seq_lock, flags); + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { + struct seq_table *ent = &intf->seq_table[i]; + + if (!ent->inuse) + continue; + deliver_err_response(intf, ent->recv_msg, IPMI_ERR_UNSPECIFIED); + } + spin_unlock_irqrestore(&intf->seq_lock, flags); +} + +static void cleanup_msgs_queue(void) +{ + struct ipmi_smi *intf; + int index; + + index = srcu_read_lock(&ipmi_interfaces_srcu); + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + struct bmc_device *bmc = intf->bmc; + + kref_get(&intf->refcount); + mutex_lock(&intf->bmc_reg_mutex); + mutex_lock(&bmc->dyn_mutex); + + __cleanup_msgs_queue(intf); + + mutex_unlock(&bmc->dyn_mutex); + mutex_unlock(&intf->bmc_reg_mutex); + kref_put(&intf->refcount, intf_free); + } + srcu_read_unlock(&ipmi_interfaces_srcu, index); +} + static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2950,6 +3018,19 @@ static ssize_t msg_count_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_ADMIN_RO(msg_count); +static ssize_t clean_msgs_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + if (!sysfs_streq(buf, "1")) + return -EINVAL; + + cleanup_msgs_queue(); + + return count; +} +static DEVICE_ATTR_WO(clean_msgs); + static struct attribute *bmc_dev_attrs[] = { &dev_attr_device_id.attr, &dev_attr_provides_device_sdrs.attr, @@ -2963,6 +3044,7 @@ static struct attribute *bmc_dev_attrs[] = { &dev_attr_guid.attr, &dev_attr_user_count.attr, &dev_attr_msg_count.attr, + &dev_attr_clean_msgs.attr, NULL }; -- 2.25.1 _______________________________________________ Openipmi-developer mailing list Openipmi-developer@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openipmi-developer