提交 b1b5bf16 编写于 作者: L Linus Torvalds

Merge tag 'for-linus-4.19-1' of https://github.com/cminyard/linux-ipmi

Pull IPMI update from Corey Minyard:
 "Add limits on the number of users and messages, plus sysfs interfaces
  to control those limits.

  Other than that, little cleanups, use dev_xxx() insted of pr_xxx(),
  create initializers for structures, fix a refcount leak, etc"

* tag 'for-linus-4.19-1' of https://github.com/cminyard/linux-ipmi:
  ipmi:ipmb: Fix refcount leak in ipmi_ipmb_probe
  ipmi: remove unnecessary type castings
  ipmi: Make two logs unique
  ipmi:si: Convert pr_debug() to dev_dbg()
  ipmi: Convert pr_debug() to dev_dbg()
  ipmi: Fix pr_fmt to avoid compilation issues
  ipmi: Add an intializer for ipmi_recv_msg struct
  ipmi: Add an intializer for ipmi_smi_msg struct
  ipmi:ssif: Check for NULL msg when handling events and messages
  ipmi: use simple i2c probe function
  ipmi: Add a sysfs count of total outstanding messages for an interface
  ipmi: Add a sysfs interface to view the number of users
  ipmi: Limit the number of message a user may have outstanding
  ipmi: Add a limit on the number of users that may use IPMI
...@@ -299,8 +299,7 @@ static int ipmb_slave_cb(struct i2c_client *client, ...@@ -299,8 +299,7 @@ static int ipmb_slave_cb(struct i2c_client *client,
return 0; return 0;
} }
static int ipmb_probe(struct i2c_client *client, static int ipmb_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct ipmb_dev *ipmb_dev; struct ipmb_dev *ipmb_dev;
int ret; int ret;
...@@ -369,7 +368,7 @@ static struct i2c_driver ipmb_driver = { ...@@ -369,7 +368,7 @@ static struct i2c_driver ipmb_driver = {
.name = "ipmb-dev", .name = "ipmb-dev",
.acpi_match_table = ACPI_PTR(acpi_ipmb_id), .acpi_match_table = ACPI_PTR(acpi_ipmb_id),
}, },
.probe = ipmb_probe, .probe_new = ipmb_probe,
.remove = ipmb_remove, .remove = ipmb_remove,
.id_table = ipmb_id, .id_table = ipmb_id,
}; };
......
...@@ -442,8 +442,7 @@ static int ipmi_ipmb_remove(struct i2c_client *client) ...@@ -442,8 +442,7 @@ static int ipmi_ipmb_remove(struct i2c_client *client)
return 0; return 0;
} }
static int ipmi_ipmb_probe(struct i2c_client *client, static int ipmi_ipmb_probe(struct i2c_client *client)
const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct ipmi_ipmb_dev *iidev; struct ipmi_ipmb_dev *iidev;
...@@ -476,6 +475,7 @@ static int ipmi_ipmb_probe(struct i2c_client *client, ...@@ -476,6 +475,7 @@ static int ipmi_ipmb_probe(struct i2c_client *client,
slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0); slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0);
if (slave_np) { if (slave_np) {
slave_adap = of_get_i2c_adapter_by_node(slave_np); slave_adap = of_get_i2c_adapter_by_node(slave_np);
of_node_put(slave_np);
if (!slave_adap) { if (!slave_adap) {
dev_notice(&client->dev, dev_notice(&client->dev,
"Could not find slave adapter\n"); "Could not find slave adapter\n");
...@@ -570,7 +570,7 @@ static struct i2c_driver ipmi_ipmb_driver = { ...@@ -570,7 +570,7 @@ static struct i2c_driver ipmi_ipmb_driver = {
.name = DEVICE_NAME, .name = DEVICE_NAME,
.of_match_table = of_ipmi_ipmb_match, .of_match_table = of_ipmi_ipmb_match,
}, },
.probe = ipmi_ipmb_probe, .probe_new = ipmi_ipmb_probe,
.remove = ipmi_ipmb_remove, .remove = ipmi_ipmb_remove,
.id_table = ipmi_ipmb_id, .id_table = ipmi_ipmb_id,
}; };
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
* Copyright 2002 MontaVista Software Inc. * Copyright 2002 MontaVista Software Inc.
*/ */
#define pr_fmt(fmt) "%s" fmt, "IPMI message handler: " #define pr_fmt(fmt) "IPMI message handler: " fmt
#define dev_fmt pr_fmt #define dev_fmt(fmt) pr_fmt(fmt)
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -145,6 +145,18 @@ module_param(default_max_retries, uint, 0644); ...@@ -145,6 +145,18 @@ module_param(default_max_retries, uint, 0644);
MODULE_PARM_DESC(default_max_retries, MODULE_PARM_DESC(default_max_retries,
"The time (milliseconds) between retry sends in maintenance mode"); "The time (milliseconds) between retry sends in maintenance mode");
/* The default maximum number of users that may register. */
static unsigned int max_users = 30;
module_param(max_users, uint, 0644);
MODULE_PARM_DESC(max_users,
"The most users that may use the IPMI stack at one time.");
/* The default maximum number of message a user may have outstanding. */
static unsigned int max_msgs_per_user = 100;
module_param(max_msgs_per_user, uint, 0644);
MODULE_PARM_DESC(max_msgs_per_user,
"The most message a user may have outstanding.");
/* Call every ~1000 ms. */ /* Call every ~1000 ms. */
#define IPMI_TIMEOUT_TIME 1000 #define IPMI_TIMEOUT_TIME 1000
...@@ -187,6 +199,8 @@ struct ipmi_user { ...@@ -187,6 +199,8 @@ struct ipmi_user {
/* Does this interface receive IPMI events? */ /* Does this interface receive IPMI events? */
bool gets_events; bool gets_events;
atomic_t nr_msgs;
/* Free must run in process context for RCU cleanup. */ /* Free must run in process context for RCU cleanup. */
struct work_struct remove_work; struct work_struct remove_work;
}; };
...@@ -442,6 +456,10 @@ struct ipmi_smi { ...@@ -442,6 +456,10 @@ struct ipmi_smi {
*/ */
struct list_head users; struct list_head users;
struct srcu_struct users_srcu; struct srcu_struct users_srcu;
atomic_t nr_users;
struct device_attribute nr_users_devattr;
struct device_attribute nr_msgs_devattr;
/* Used for wake ups at startup. */ /* Used for wake ups at startup. */
wait_queue_head_t waitq; wait_queue_head_t waitq;
...@@ -927,11 +945,13 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg) ...@@ -927,11 +945,13 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
* risk. At this moment, simply skip it in that case. * risk. At this moment, simply skip it in that case.
*/ */
ipmi_free_recv_msg(msg); ipmi_free_recv_msg(msg);
atomic_dec(&msg->user->nr_msgs);
} else { } else {
int index; int index;
struct ipmi_user *user = acquire_ipmi_user(msg->user, &index); struct ipmi_user *user = acquire_ipmi_user(msg->user, &index);
if (user) { if (user) {
atomic_dec(&user->nr_msgs);
user->handler->ipmi_recv_hndl(msg, user->handler_data); user->handler->ipmi_recv_hndl(msg, user->handler_data);
release_ipmi_user(user, index); release_ipmi_user(user, index);
} else { } else {
...@@ -1230,6 +1250,11 @@ int ipmi_create_user(unsigned int if_num, ...@@ -1230,6 +1250,11 @@ int ipmi_create_user(unsigned int if_num,
goto out_kfree; goto out_kfree;
found: found:
if (atomic_add_return(1, &intf->nr_users) > max_users) {
rv = -EBUSY;
goto out_kfree;
}
INIT_WORK(&new_user->remove_work, free_user_work); INIT_WORK(&new_user->remove_work, free_user_work);
rv = init_srcu_struct(&new_user->release_barrier); rv = init_srcu_struct(&new_user->release_barrier);
...@@ -1244,6 +1269,7 @@ int ipmi_create_user(unsigned int if_num, ...@@ -1244,6 +1269,7 @@ int ipmi_create_user(unsigned int if_num,
/* Note that each existing user holds a refcount to the interface. */ /* Note that each existing user holds a refcount to the interface. */
kref_get(&intf->refcount); kref_get(&intf->refcount);
atomic_set(&new_user->nr_msgs, 0);
kref_init(&new_user->refcount); kref_init(&new_user->refcount);
new_user->handler = handler; new_user->handler = handler;
new_user->handler_data = handler_data; new_user->handler_data = handler_data;
...@@ -1262,6 +1288,7 @@ int ipmi_create_user(unsigned int if_num, ...@@ -1262,6 +1288,7 @@ int ipmi_create_user(unsigned int if_num,
return 0; return 0;
out_kfree: out_kfree:
atomic_dec(&intf->nr_users);
srcu_read_unlock(&ipmi_interfaces_srcu, index); srcu_read_unlock(&ipmi_interfaces_srcu, index);
vfree(new_user); vfree(new_user);
return rv; return rv;
...@@ -1336,6 +1363,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user) ...@@ -1336,6 +1363,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
/* Remove the user from the interface's sequence table. */ /* Remove the user from the interface's sequence table. */
spin_lock_irqsave(&intf->seq_lock, flags); spin_lock_irqsave(&intf->seq_lock, flags);
list_del_rcu(&user->link); list_del_rcu(&user->link);
atomic_dec(&intf->nr_users);
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
if (intf->seq_table[i].inuse if (intf->seq_table[i].inuse
...@@ -2284,6 +2312,14 @@ static int i_ipmi_request(struct ipmi_user *user, ...@@ -2284,6 +2312,14 @@ static int i_ipmi_request(struct ipmi_user *user,
struct ipmi_recv_msg *recv_msg; struct ipmi_recv_msg *recv_msg;
int rv = 0; int rv = 0;
if (user) {
if (atomic_add_return(1, &user->nr_msgs) > max_msgs_per_user) {
/* Decrement will happen at the end of the routine. */
rv = -EBUSY;
goto out;
}
}
if (supplied_recv) if (supplied_recv)
recv_msg = supplied_recv; recv_msg = supplied_recv;
else { else {
...@@ -2296,7 +2332,7 @@ static int i_ipmi_request(struct ipmi_user *user, ...@@ -2296,7 +2332,7 @@ static int i_ipmi_request(struct ipmi_user *user,
recv_msg->user_msg_data = user_msg_data; recv_msg->user_msg_data = user_msg_data;
if (supplied_smi) if (supplied_smi)
smi_msg = (struct ipmi_smi_msg *) supplied_smi; smi_msg = supplied_smi;
else { else {
smi_msg = ipmi_alloc_smi_msg(); smi_msg = ipmi_alloc_smi_msg();
if (smi_msg == NULL) { if (smi_msg == NULL) {
...@@ -2348,13 +2384,16 @@ static int i_ipmi_request(struct ipmi_user *user, ...@@ -2348,13 +2384,16 @@ static int i_ipmi_request(struct ipmi_user *user,
ipmi_free_smi_msg(smi_msg); ipmi_free_smi_msg(smi_msg);
ipmi_free_recv_msg(recv_msg); ipmi_free_recv_msg(recv_msg);
} else { } else {
pr_debug("Send: %*ph\n", smi_msg->data_size, smi_msg->data); dev_dbg(intf->si_dev, "Send: %*ph\n",
smi_msg->data_size, smi_msg->data);
smi_send(intf, intf->handlers, smi_msg, priority); smi_send(intf, intf->handlers, smi_msg, priority);
} }
rcu_read_unlock(); rcu_read_unlock();
out: out:
if (rv && user)
atomic_dec(&user->nr_msgs);
return rv; return rv;
} }
...@@ -3471,6 +3510,36 @@ void ipmi_poll_interface(struct ipmi_user *user) ...@@ -3471,6 +3510,36 @@ void ipmi_poll_interface(struct ipmi_user *user)
} }
EXPORT_SYMBOL(ipmi_poll_interface); EXPORT_SYMBOL(ipmi_poll_interface);
static ssize_t nr_users_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ipmi_smi *intf = container_of(attr,
struct ipmi_smi, nr_users_devattr);
return sysfs_emit(buf, "%d\n", atomic_read(&intf->nr_users));
}
static DEVICE_ATTR_RO(nr_users);
static ssize_t nr_msgs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ipmi_smi *intf = container_of(attr,
struct ipmi_smi, nr_msgs_devattr);
struct ipmi_user *user;
int index;
unsigned int count = 0;
index = srcu_read_lock(&intf->users_srcu);
list_for_each_entry_rcu(user, &intf->users, link)
count += atomic_read(&user->nr_msgs);
srcu_read_unlock(&intf->users_srcu, index);
return sysfs_emit(buf, "%u\n", count);
}
static DEVICE_ATTR_RO(nr_msgs);
static void redo_bmc_reg(struct work_struct *work) static void redo_bmc_reg(struct work_struct *work)
{ {
struct ipmi_smi *intf = container_of(work, struct ipmi_smi, struct ipmi_smi *intf = container_of(work, struct ipmi_smi,
...@@ -3529,6 +3598,7 @@ int ipmi_add_smi(struct module *owner, ...@@ -3529,6 +3598,7 @@ int ipmi_add_smi(struct module *owner,
if (slave_addr != 0) if (slave_addr != 0)
intf->addrinfo[0].address = slave_addr; intf->addrinfo[0].address = slave_addr;
INIT_LIST_HEAD(&intf->users); INIT_LIST_HEAD(&intf->users);
atomic_set(&intf->nr_users, 0);
intf->handlers = handlers; intf->handlers = handlers;
intf->send_info = send_info; intf->send_info = send_info;
spin_lock_init(&intf->seq_lock); spin_lock_init(&intf->seq_lock);
...@@ -3592,6 +3662,20 @@ int ipmi_add_smi(struct module *owner, ...@@ -3592,6 +3662,20 @@ int ipmi_add_smi(struct module *owner,
if (rv) if (rv)
goto out_err_bmc_reg; goto out_err_bmc_reg;
intf->nr_users_devattr = dev_attr_nr_users;
sysfs_attr_init(&intf->nr_users_devattr.attr);
rv = device_create_file(intf->si_dev, &intf->nr_users_devattr);
if (rv)
goto out_err_bmc_reg;
intf->nr_msgs_devattr = dev_attr_nr_msgs;
sysfs_attr_init(&intf->nr_msgs_devattr.attr);
rv = device_create_file(intf->si_dev, &intf->nr_msgs_devattr);
if (rv) {
device_remove_file(intf->si_dev, &intf->nr_users_devattr);
goto out_err_bmc_reg;
}
/* /*
* Keep memory order straight for RCU readers. Make * Keep memory order straight for RCU readers. Make
* sure everything else is committed to memory before * sure everything else is committed to memory before
...@@ -3691,6 +3775,9 @@ void ipmi_unregister_smi(struct ipmi_smi *intf) ...@@ -3691,6 +3775,9 @@ void ipmi_unregister_smi(struct ipmi_smi *intf)
/* At this point no users can be added to the interface. */ /* At this point no users can be added to the interface. */
device_remove_file(intf->si_dev, &intf->nr_msgs_devattr);
device_remove_file(intf->si_dev, &intf->nr_users_devattr);
/* /*
* Call all the watcher interfaces to tell them that * Call all the watcher interfaces to tell them that
* an interface is going away. * an interface is going away.
...@@ -3839,7 +3926,8 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf, ...@@ -3839,7 +3926,8 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
msg->data[10] = ipmb_checksum(&msg->data[6], 4); msg->data[10] = ipmb_checksum(&msg->data[6], 4);
msg->data_size = 11; msg->data_size = 11;
pr_debug("Invalid command: %*ph\n", msg->data_size, msg->data); dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
msg->data_size, msg->data);
rcu_read_lock(); rcu_read_lock();
if (!intf->in_shutdown) { if (!intf->in_shutdown) {
...@@ -3992,10 +4080,10 @@ static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf, ...@@ -3992,10 +4080,10 @@ static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf,
struct ipmi_recv_msg *recv_msg; struct ipmi_recv_msg *recv_msg;
struct ipmi_ipmb_direct_addr *daddr; struct ipmi_ipmb_direct_addr *daddr;
recv_msg = (struct ipmi_recv_msg *) msg->user_data; recv_msg = msg->user_data;
if (recv_msg == NULL) { if (recv_msg == NULL) {
dev_warn(intf->si_dev, dev_warn(intf->si_dev,
"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"); "IPMI direct 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");
return 0; return 0;
} }
...@@ -4410,10 +4498,10 @@ static int handle_bmc_rsp(struct ipmi_smi *intf, ...@@ -4410,10 +4498,10 @@ static int handle_bmc_rsp(struct ipmi_smi *intf,
struct ipmi_recv_msg *recv_msg; struct ipmi_recv_msg *recv_msg;
struct ipmi_system_interface_addr *smi_addr; struct ipmi_system_interface_addr *smi_addr;
recv_msg = (struct ipmi_recv_msg *) msg->user_data; recv_msg = msg->user_data;
if (recv_msg == NULL) { if (recv_msg == NULL) {
dev_warn(intf->si_dev, dev_warn(intf->si_dev,
"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"); "IPMI SMI 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");
return 0; return 0;
} }
...@@ -4447,7 +4535,7 @@ static int handle_one_recv_msg(struct ipmi_smi *intf, ...@@ -4447,7 +4535,7 @@ static int handle_one_recv_msg(struct ipmi_smi *intf,
unsigned char cc; unsigned char cc;
bool is_cmd = !((msg->rsp[0] >> 2) & 1); bool is_cmd = !((msg->rsp[0] >> 2) & 1);
pr_debug("Recv: %*ph\n", msg->rsp_size, msg->rsp); dev_dbg(intf->si_dev, "Recv: %*ph\n", msg->rsp_size, msg->rsp);
if (msg->rsp_size < 2) { if (msg->rsp_size < 2) {
/* Message is too small to be correct. */ /* Message is too small to be correct. */
...@@ -4831,7 +4919,8 @@ smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg, ...@@ -4831,7 +4919,8 @@ smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg,
smi_msg->data_size = recv_msg->msg.data_len; smi_msg->data_size = recv_msg->msg.data_len;
smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
pr_debug("Resend: %*ph\n", smi_msg->data_size, smi_msg->data); dev_dbg(intf->si_dev, "Resend: %*ph\n",
smi_msg->data_size, smi_msg->data);
return smi_msg; return smi_msg;
} }
......
...@@ -94,12 +94,8 @@ static void dummy_recv_free(struct ipmi_recv_msg *msg) ...@@ -94,12 +94,8 @@ static void dummy_recv_free(struct ipmi_recv_msg *msg)
{ {
atomic_dec(&dummy_count); atomic_dec(&dummy_count);
} }
static struct ipmi_smi_msg halt_smi_msg = { static struct ipmi_smi_msg halt_smi_msg = INIT_IPMI_SMI_MSG(dummy_smi_free);
.done = dummy_smi_free static struct ipmi_recv_msg halt_recv_msg = INIT_IPMI_RECV_MSG(dummy_recv_free);
};
static struct ipmi_recv_msg halt_recv_msg = {
.done = dummy_recv_free
};
/* /*
......
...@@ -264,15 +264,16 @@ static void cleanup_one_si(struct smi_info *smi_info); ...@@ -264,15 +264,16 @@ static void cleanup_one_si(struct smi_info *smi_info);
static void cleanup_ipmi_si(void); static void cleanup_ipmi_si(void);
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
void debug_timestamp(char *msg) void debug_timestamp(struct smi_info *smi_info, char *msg)
{ {
struct timespec64 t; struct timespec64 t;
ktime_get_ts64(&t); ktime_get_ts64(&t);
pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec); dev_dbg(smi_info->io.dev, "**%s: %lld.%9.9ld\n",
msg, t.tv_sec, t.tv_nsec);
} }
#else #else
#define debug_timestamp(x) #define debug_timestamp(smi_info, x)
#endif #endif
static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
...@@ -318,7 +319,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) ...@@ -318,7 +319,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
smi_info->curr_msg = smi_info->waiting_msg; smi_info->curr_msg = smi_info->waiting_msg;
smi_info->waiting_msg = NULL; smi_info->waiting_msg = NULL;
debug_timestamp("Start2"); debug_timestamp(smi_info, "Start2");
err = atomic_notifier_call_chain(&xaction_notifier_list, err = atomic_notifier_call_chain(&xaction_notifier_list,
0, smi_info); 0, smi_info);
if (err & NOTIFY_STOP_MASK) { if (err & NOTIFY_STOP_MASK) {
...@@ -538,7 +539,7 @@ static void handle_transaction_done(struct smi_info *smi_info) ...@@ -538,7 +539,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
{ {
struct ipmi_smi_msg *msg; struct ipmi_smi_msg *msg;
debug_timestamp("Done"); debug_timestamp(smi_info, "Done");
switch (smi_info->si_state) { switch (smi_info->si_state) {
case SI_NORMAL: case SI_NORMAL:
if (!smi_info->curr_msg) if (!smi_info->curr_msg)
...@@ -901,7 +902,7 @@ static void sender(void *send_info, ...@@ -901,7 +902,7 @@ static void sender(void *send_info,
struct smi_info *smi_info = send_info; struct smi_info *smi_info = send_info;
unsigned long flags; unsigned long flags;
debug_timestamp("Enqueue"); debug_timestamp(smi_info, "Enqueue");
if (smi_info->run_to_completion) { if (smi_info->run_to_completion) {
/* /*
...@@ -1079,7 +1080,7 @@ static void smi_timeout(struct timer_list *t) ...@@ -1079,7 +1080,7 @@ static void smi_timeout(struct timer_list *t)
long timeout; long timeout;
spin_lock_irqsave(&(smi_info->si_lock), flags); spin_lock_irqsave(&(smi_info->si_lock), flags);
debug_timestamp("Timer"); debug_timestamp(smi_info, "Timer");
jiffies_now = jiffies; jiffies_now = jiffies;
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies) time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
...@@ -1128,7 +1129,7 @@ irqreturn_t ipmi_si_irq_handler(int irq, void *data) ...@@ -1128,7 +1129,7 @@ irqreturn_t ipmi_si_irq_handler(int irq, void *data)
smi_inc_stat(smi_info, interrupts); smi_inc_stat(smi_info, interrupts);
debug_timestamp("Interrupt"); debug_timestamp(smi_info, "Interrupt");
smi_event_handler(smi_info, 0); smi_event_handler(smi_info, 0);
spin_unlock_irqrestore(&(smi_info->si_lock), flags); spin_unlock_irqrestore(&(smi_info->si_lock), flags);
......
...@@ -814,6 +814,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ...@@ -814,6 +814,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
break; break;
case SSIF_GETTING_EVENTS: case SSIF_GETTING_EVENTS:
if (!msg) {
/* Should never happen, but just in case. */
dev_warn(&ssif_info->client->dev,
"No message set while getting events\n");
ipmi_ssif_unlock_cond(ssif_info, flags);
break;
}
if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
/* Error getting event, probably done. */ /* Error getting event, probably done. */
msg->done(msg); msg->done(msg);
...@@ -838,6 +846,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ...@@ -838,6 +846,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
break; break;
case SSIF_GETTING_MESSAGES: case SSIF_GETTING_MESSAGES:
if (!msg) {
/* Should never happen, but just in case. */
dev_warn(&ssif_info->client->dev,
"No message set while getting messages\n");
ipmi_ssif_unlock_cond(ssif_info, flags);
break;
}
if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
/* Error getting event, probably done. */ /* Error getting event, probably done. */
msg->done(msg); msg->done(msg);
...@@ -861,6 +877,13 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, ...@@ -861,6 +877,13 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
deliver_recv_msg(ssif_info, msg); deliver_recv_msg(ssif_info, msg);
} }
break; break;
default:
/* Should never happen, but just in case. */
dev_warn(&ssif_info->client->dev,
"Invalid state in message done handling: %d\n",
ssif_info->ssif_state);
ipmi_ssif_unlock_cond(ssif_info, flags);
} }
flags = ipmi_ssif_lock_cond(ssif_info, &oflags); flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
...@@ -1053,7 +1076,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags) ...@@ -1053,7 +1076,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags)
static void sender(void *send_info, static void sender(void *send_info,
struct ipmi_smi_msg *msg) struct ipmi_smi_msg *msg)
{ {
struct ssif_info *ssif_info = (struct ssif_info *) send_info; struct ssif_info *ssif_info = send_info;
unsigned long oflags, *flags; unsigned long oflags, *flags;
BUG_ON(ssif_info->waiting_msg); BUG_ON(ssif_info->waiting_msg);
...@@ -1090,7 +1113,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data) ...@@ -1090,7 +1113,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
*/ */
static void request_events(void *send_info) static void request_events(void *send_info)
{ {
struct ssif_info *ssif_info = (struct ssif_info *) send_info; struct ssif_info *ssif_info = send_info;
unsigned long oflags, *flags; unsigned long oflags, *flags;
if (!ssif_info->has_event_buffer) if (!ssif_info->has_event_buffer)
...@@ -1107,7 +1130,7 @@ static void request_events(void *send_info) ...@@ -1107,7 +1130,7 @@ static void request_events(void *send_info)
*/ */
static void ssif_set_need_watch(void *send_info, unsigned int watch_mask) static void ssif_set_need_watch(void *send_info, unsigned int watch_mask)
{ {
struct ssif_info *ssif_info = (struct ssif_info *) send_info; struct ssif_info *ssif_info = send_info;
unsigned long oflags, *flags; unsigned long oflags, *flags;
long timeout = 0; long timeout = 0;
...@@ -1619,7 +1642,7 @@ static int ssif_check_and_remove(struct i2c_client *client, ...@@ -1619,7 +1642,7 @@ static int ssif_check_and_remove(struct i2c_client *client,
return 0; return 0;
} }
static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) static int ssif_probe(struct i2c_client *client)
{ {
unsigned char msg[3]; unsigned char msg[3];
unsigned char *resp; unsigned char *resp;
...@@ -2037,7 +2060,7 @@ static struct i2c_driver ssif_i2c_driver = { ...@@ -2037,7 +2060,7 @@ static struct i2c_driver ssif_i2c_driver = {
.driver = { .driver = {
.name = DEVICE_NAME .name = DEVICE_NAME
}, },
.probe = ssif_probe, .probe_new = ssif_probe,
.remove = ssif_remove, .remove = ssif_remove,
.alert = ssif_alert, .alert = ssif_alert,
.id_table = ssif_id, .id_table = ssif_id,
......
...@@ -354,12 +354,8 @@ static void msg_free_recv(struct ipmi_recv_msg *msg) ...@@ -354,12 +354,8 @@ static void msg_free_recv(struct ipmi_recv_msg *msg)
complete(&msg_wait); complete(&msg_wait);
} }
} }
static struct ipmi_smi_msg smi_msg = { static struct ipmi_smi_msg smi_msg = INIT_IPMI_SMI_MSG(msg_free_smi);
.done = msg_free_smi static struct ipmi_recv_msg recv_msg = INIT_IPMI_RECV_MSG(msg_free_recv);
};
static struct ipmi_recv_msg recv_msg = {
.done = msg_free_recv
};
static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg, struct ipmi_recv_msg *recv_msg,
...@@ -475,12 +471,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg) ...@@ -475,12 +471,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg)
atomic_dec(&panic_done_count); atomic_dec(&panic_done_count);
} }
static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = { static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
.done = panic_smi_free INIT_IPMI_SMI_MSG(panic_smi_free);
}; static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = { INIT_IPMI_RECV_MSG(panic_recv_free);
.done = panic_recv_free
};
static void panic_halt_ipmi_heartbeat(void) static void panic_halt_ipmi_heartbeat(void)
{ {
...@@ -516,12 +510,10 @@ static void panic_halt_ipmi_heartbeat(void) ...@@ -516,12 +510,10 @@ static void panic_halt_ipmi_heartbeat(void)
atomic_sub(2, &panic_done_count); atomic_sub(2, &panic_done_count);
} }
static struct ipmi_smi_msg panic_halt_smi_msg = { static struct ipmi_smi_msg panic_halt_smi_msg =
.done = panic_smi_free INIT_IPMI_SMI_MSG(panic_smi_free);
}; static struct ipmi_recv_msg panic_halt_recv_msg =
static struct ipmi_recv_msg panic_halt_recv_msg = { INIT_IPMI_RECV_MSG(panic_recv_free);
.done = panic_recv_free
};
/* /*
* Special call, doesn't claim any locks. This is only to be called * Special call, doesn't claim any locks. This is only to be called
......
...@@ -72,6 +72,11 @@ struct ipmi_recv_msg { ...@@ -72,6 +72,11 @@ struct ipmi_recv_msg {
unsigned char msg_data[IPMI_MAX_MSG_LENGTH]; unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
}; };
#define INIT_IPMI_RECV_MSG(done_handler) \
{ \
.done = done_handler \
}
/* Allocate and free the receive message. */ /* Allocate and free the receive message. */
void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); void ipmi_free_recv_msg(struct ipmi_recv_msg *msg);
......
...@@ -125,6 +125,12 @@ struct ipmi_smi_msg { ...@@ -125,6 +125,12 @@ struct ipmi_smi_msg {
void (*done)(struct ipmi_smi_msg *msg); void (*done)(struct ipmi_smi_msg *msg);
}; };
#define INIT_IPMI_SMI_MSG(done_handler) \
{ \
.done = done_handler, \
.type = IPMI_SMI_MSG_TYPE_NORMAL \
}
struct ipmi_smi_handlers { struct ipmi_smi_handlers {
struct module *owner; struct module *owner;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册