Commit a794b4f3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-4.3' of git://git.code.sf.net/p/openipmi/linux-ipmi

Pull IPMI updates from Corey Minyard:
 "Most of these have been sitting in linux-next for more than a release,
  particularly commit 0fbcf4af ("ipmi: Convert the IPMI SI ACPI
  handling to a platform device") which is probably the most complex
  patch.

  That is also the one that changes drivers/acpi/acpi_pnp.c.  The change
  in that file is only removing IPMI from a "special platform devices"
  list, since I convert it to the standard PNP interface.  I posted this
  one to the ACPI list twice and got no response, and it seems to work
  well in my testing, so I'm hoping it's good.

  Hidehiro Kawai posted a set of changes that improves the panic time
  handling in the IPMI driver.

  The rest of the changes are minor bug fixes or cleanups and some
  documentation"

* tag 'for-linus-4.3' of git://git.code.sf.net/p/openipmi/linux-ipmi:
  ipmi:ssif: Add a module parm to specify that SMBus alerts don't work
  ipmi: add of_device_id in MODULE_DEVICE_TABLE
  ipmi: Compensate for BMCs that wont set the irq enable bit
  ipmi: Don't call receive handler in the panic context
  ipmi: Avoid touching possible corrupted lists in the panic context
  ipmi: Don't flush messages in sender() in run-to-completion mode
  ipmi: Factor out message flushing procedure
  ipmi: Remove unneeded set_run_to_completion call
  ipmi: Make some data const that was only read
  ipmi: constify SSIF ACPI device ids
  ipmi: Delete an unnecessary check before the function call "cleanup_one_si"
  char:ipmi - Change 1 to true for bool type variables during initialization.
  impi:Remove unneeded setting of module owner to THIS_MODULE in the platform structure, powernv_ipmi_driver
  ipmi: Add a comment in how messages are delivered from the lower layer
  ipmi/powernv: Fix potential invalid pointer dereference
  ipmi: Convert the IPMI SI ACPI handling to a platform device
  ipmi: Add device tree bindings information
parents f6f7a636 bf2d0877
IPMI device
Required properties:
- compatible: should be one of ipmi-kcs, ipmi-smic, or ipmi-bt
- device_type: should be ipmi
- reg: Address and length of the register set for the device
Optional properties:
- interrupts: The interrupt for the device. Without this the interface
is polled.
- reg-size - The size of the register. Defaults to 1
- reg-spacing - The number of bytes between register starts. Defaults to 1
- reg-shift - The amount to shift the registers to the right to get the data
into bit zero.
Example:
smic@fff3a000 {
compatible = "ipmi-smic";
device_type = "ipmi";
reg = <0xfff3a000 0x1000>;
interrupts = <0 24 4>;
reg-size = <4>;
reg-spacing = <4>;
};
...@@ -19,8 +19,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { ...@@ -19,8 +19,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */
/* floppy */ /* floppy */
{"PNP0700"}, {"PNP0700"},
/* ipmi_si */
{"IPI0001"},
/* tpm_inf_pnp */ /* tpm_inf_pnp */
{"IFX0101"}, /* Infineon TPMs */ {"IFX0101"}, /* Infineon TPMs */
{"IFX0102"}, /* Infineon TPMs */ {"IFX0102"}, /* Infineon TPMs */
......
...@@ -694,7 +694,7 @@ static int bt_size(void) ...@@ -694,7 +694,7 @@ static int bt_size(void)
return sizeof(struct si_sm_data); return sizeof(struct si_sm_data);
} }
struct si_sm_handlers bt_smi_handlers = { const struct si_sm_handlers bt_smi_handlers = {
.init_data = bt_init_data, .init_data = bt_init_data,
.start_transaction = bt_start_transaction, .start_transaction = bt_start_transaction,
.get_result = bt_get_result, .get_result = bt_get_result,
......
...@@ -540,7 +540,7 @@ static void kcs_cleanup(struct si_sm_data *kcs) ...@@ -540,7 +540,7 @@ static void kcs_cleanup(struct si_sm_data *kcs)
{ {
} }
struct si_sm_handlers kcs_smi_handlers = { const struct si_sm_handlers kcs_smi_handlers = {
.init_data = init_kcs_data, .init_data = init_kcs_data,
.start_transaction = start_kcs_transaction, .start_transaction = start_kcs_transaction,
.get_result = get_kcs_result, .get_result = get_kcs_result,
......
...@@ -342,7 +342,7 @@ struct ipmi_smi { ...@@ -342,7 +342,7 @@ struct ipmi_smi {
* an umpreemptible region to use this. You must fetch the * an umpreemptible region to use this. You must fetch the
* value into a local variable and make sure it is not NULL. * value into a local variable and make sure it is not NULL.
*/ */
struct ipmi_smi_handlers *handlers; const struct ipmi_smi_handlers *handlers;
void *send_info; void *send_info;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
...@@ -744,7 +744,13 @@ static void deliver_response(struct ipmi_recv_msg *msg) ...@@ -744,7 +744,13 @@ static void deliver_response(struct ipmi_recv_msg *msg)
ipmi_inc_stat(intf, unhandled_local_responses); ipmi_inc_stat(intf, unhandled_local_responses);
} }
ipmi_free_recv_msg(msg); ipmi_free_recv_msg(msg);
} else { } else if (!oops_in_progress) {
/*
* If we are running in the panic context, calling the
* receive handler doesn't much meaning and has a deadlock
* risk. At this moment, simply skip it in that case.
*/
ipmi_user_t user = msg->user; ipmi_user_t user = msg->user;
user->handler->ipmi_recv_hndl(msg, user->handler_data); user->handler->ipmi_recv_hndl(msg, user->handler_data);
} }
...@@ -1015,7 +1021,7 @@ int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data) ...@@ -1015,7 +1021,7 @@ int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
{ {
int rv = 0; int rv = 0;
ipmi_smi_t intf; ipmi_smi_t intf;
struct ipmi_smi_handlers *handlers; const struct ipmi_smi_handlers *handlers;
mutex_lock(&ipmi_interfaces_mutex); mutex_lock(&ipmi_interfaces_mutex);
list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
...@@ -1501,7 +1507,7 @@ static struct ipmi_smi_msg *smi_add_send_msg(ipmi_smi_t intf, ...@@ -1501,7 +1507,7 @@ static struct ipmi_smi_msg *smi_add_send_msg(ipmi_smi_t intf,
} }
static void smi_send(ipmi_smi_t intf, struct ipmi_smi_handlers *handlers, static void smi_send(ipmi_smi_t intf, const struct ipmi_smi_handlers *handlers,
struct ipmi_smi_msg *smi_msg, int priority) struct ipmi_smi_msg *smi_msg, int priority)
{ {
int run_to_completion = intf->run_to_completion; int run_to_completion = intf->run_to_completion;
...@@ -2747,7 +2753,7 @@ void ipmi_poll_interface(ipmi_user_t user) ...@@ -2747,7 +2753,7 @@ void ipmi_poll_interface(ipmi_user_t user)
} }
EXPORT_SYMBOL(ipmi_poll_interface); EXPORT_SYMBOL(ipmi_poll_interface);
int ipmi_register_smi(struct ipmi_smi_handlers *handlers, int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
void *send_info, void *send_info,
struct ipmi_device_id *device_id, struct ipmi_device_id *device_id,
struct device *si_dev, struct device *si_dev,
...@@ -3959,6 +3965,10 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, ...@@ -3959,6 +3965,10 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
if (!run_to_completion) if (!run_to_completion)
spin_lock_irqsave(&intf->xmit_msgs_lock, flags); spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
/*
* We can get an asynchronous event or receive message in addition
* to commands we send.
*/
if (msg == intf->curr_msg) if (msg == intf->curr_msg)
intf->curr_msg = NULL; intf->curr_msg = NULL;
if (!run_to_completion) if (!run_to_completion)
...@@ -4015,7 +4025,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, ...@@ -4015,7 +4025,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
unsigned int *waiting_msgs) unsigned int *waiting_msgs)
{ {
struct ipmi_recv_msg *msg; struct ipmi_recv_msg *msg;
struct ipmi_smi_handlers *handlers; const struct ipmi_smi_handlers *handlers;
if (intf->in_shutdown) if (intf->in_shutdown)
return; return;
...@@ -4082,7 +4092,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, ...@@ -4082,7 +4092,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
ipmi_inc_stat(intf, ipmi_inc_stat(intf,
retransmitted_ipmb_commands); retransmitted_ipmb_commands);
smi_send(intf, intf->handlers, smi_msg, 0); smi_send(intf, handlers, smi_msg, 0);
} else } else
ipmi_free_smi_msg(smi_msg); ipmi_free_smi_msg(smi_msg);
...@@ -4291,6 +4301,9 @@ static void ipmi_panic_request_and_wait(ipmi_smi_t intf, ...@@ -4291,6 +4301,9 @@ static void ipmi_panic_request_and_wait(ipmi_smi_t intf,
0, 1); /* Don't retry, and don't wait. */ 0, 1); /* Don't retry, and don't wait. */
if (rv) if (rv)
atomic_sub(2, &panic_done_count); atomic_sub(2, &panic_done_count);
else if (intf->handlers->flush_messages)
intf->handlers->flush_messages(intf->send_info);
while (atomic_read(&panic_done_count) != 0) while (atomic_read(&panic_done_count) != 0)
ipmi_poll(intf); ipmi_poll(intf);
} }
...@@ -4364,9 +4377,7 @@ static void send_panic_events(char *str) ...@@ -4364,9 +4377,7 @@ static void send_panic_events(char *str)
/* Interface is not ready. */ /* Interface is not ready. */
continue; continue;
intf->run_to_completion = 1;
/* Send the event announcing the panic. */ /* Send the event announcing the panic. */
intf->handlers->set_run_to_completion(intf->send_info, 1);
ipmi_panic_request_and_wait(intf, &addr, &msg); ipmi_panic_request_and_wait(intf, &addr, &msg);
} }
...@@ -4506,6 +4517,23 @@ static int panic_event(struct notifier_block *this, ...@@ -4506,6 +4517,23 @@ static int panic_event(struct notifier_block *this,
/* Interface is not ready. */ /* Interface is not ready. */
continue; continue;
/*
* If we were interrupted while locking xmit_msgs_lock or
* waiting_rcv_msgs_lock, the corresponding list may be
* corrupted. In this case, drop items on the list for
* the safety.
*/
if (!spin_trylock(&intf->xmit_msgs_lock)) {
INIT_LIST_HEAD(&intf->xmit_msgs);
INIT_LIST_HEAD(&intf->hp_xmit_msgs);
} else
spin_unlock(&intf->xmit_msgs_lock);
if (!spin_trylock(&intf->waiting_rcv_msgs_lock))
INIT_LIST_HEAD(&intf->waiting_rcv_msgs);
else
spin_unlock(&intf->waiting_rcv_msgs_lock);
intf->run_to_completion = 1; intf->run_to_completion = 1;
intf->handlers->set_run_to_completion(intf->send_info, 1); intf->handlers->set_run_to_completion(intf->send_info, 1);
} }
......
...@@ -143,8 +143,15 @@ static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi) ...@@ -143,8 +143,15 @@ static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi)
pr_devel("%s: -> %d (size %lld)\n", __func__, pr_devel("%s: -> %d (size %lld)\n", __func__,
rc, rc == 0 ? size : 0); rc, rc == 0 ? size : 0);
if (rc) { if (rc) {
/* If came via the poll, and response was not yet ready */
if (rc == OPAL_EMPTY) {
spin_unlock_irqrestore(&smi->msg_lock, flags);
return 0;
}
smi->cur_msg = NULL;
spin_unlock_irqrestore(&smi->msg_lock, flags); spin_unlock_irqrestore(&smi->msg_lock, flags);
ipmi_free_smi_msg(msg); send_error_reply(smi, msg, IPMI_ERR_UNSPECIFIED);
return 0; return 0;
} }
...@@ -300,7 +307,6 @@ static const struct of_device_id ipmi_powernv_match[] = { ...@@ -300,7 +307,6 @@ static const struct of_device_id ipmi_powernv_match[] = {
static struct platform_driver powernv_ipmi_driver = { static struct platform_driver powernv_ipmi_driver = {
.driver = { .driver = {
.name = "ipmi-powernv", .name = "ipmi-powernv",
.owner = THIS_MODULE,
.of_match_table = ipmi_powernv_match, .of_match_table = ipmi_powernv_match,
}, },
.probe = ipmi_powernv_probe, .probe = ipmi_powernv_probe,
......
This diff is collapsed.
...@@ -46,8 +46,8 @@ struct si_sm_data; ...@@ -46,8 +46,8 @@ struct si_sm_data;
* this interface. * this interface.
*/ */
struct si_sm_io { struct si_sm_io {
unsigned char (*inputb)(struct si_sm_io *io, unsigned int offset); unsigned char (*inputb)(const struct si_sm_io *io, unsigned int offset);
void (*outputb)(struct si_sm_io *io, void (*outputb)(const struct si_sm_io *io,
unsigned int offset, unsigned int offset,
unsigned char b); unsigned char b);
...@@ -135,7 +135,7 @@ struct si_sm_handlers { ...@@ -135,7 +135,7 @@ struct si_sm_handlers {
}; };
/* Current state machines that we can use. */ /* Current state machines that we can use. */
extern struct si_sm_handlers kcs_smi_handlers; extern const struct si_sm_handlers kcs_smi_handlers;
extern struct si_sm_handlers smic_smi_handlers; extern const struct si_sm_handlers smic_smi_handlers;
extern struct si_sm_handlers bt_smi_handlers; extern const struct si_sm_handlers bt_smi_handlers;
...@@ -589,7 +589,7 @@ static int smic_size(void) ...@@ -589,7 +589,7 @@ static int smic_size(void)
return sizeof(struct si_sm_data); return sizeof(struct si_sm_data);
} }
struct si_sm_handlers smic_smi_handlers = { const struct si_sm_handlers smic_smi_handlers = {
.init_data = init_smic_data, .init_data = init_smic_data,
.start_transaction = start_smic_transaction, .start_transaction = start_smic_transaction,
.get_result = smic_get_result, .get_result = smic_get_result,
......
...@@ -1136,6 +1136,10 @@ module_param_array(slave_addrs, int, &num_slave_addrs, 0); ...@@ -1136,6 +1136,10 @@ module_param_array(slave_addrs, int, &num_slave_addrs, 0);
MODULE_PARM_DESC(slave_addrs, MODULE_PARM_DESC(slave_addrs,
"The default IPMB slave address for the controller."); "The default IPMB slave address for the controller.");
static bool alerts_broken;
module_param(alerts_broken, bool, 0);
MODULE_PARM_DESC(alerts_broken, "Don't enable alerts for the controller.");
/* /*
* Bit 0 enables message debugging, bit 1 enables state debugging, and * Bit 0 enables message debugging, bit 1 enables state debugging, and
* bit 2 enables timing debugging. This is an array indexed by * bit 2 enables timing debugging. This is an array indexed by
...@@ -1154,11 +1158,11 @@ static int use_thread; ...@@ -1154,11 +1158,11 @@ static int use_thread;
module_param(use_thread, int, 0); module_param(use_thread, int, 0);
MODULE_PARM_DESC(use_thread, "Use the thread interface."); MODULE_PARM_DESC(use_thread, "Use the thread interface.");
static bool ssif_tryacpi = 1; static bool ssif_tryacpi = true;
module_param_named(tryacpi, ssif_tryacpi, bool, 0); module_param_named(tryacpi, ssif_tryacpi, bool, 0);
MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI"); MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI");
static bool ssif_trydmi = 1; static bool ssif_trydmi = true;
module_param_named(trydmi, ssif_trydmi, bool, 0); module_param_named(trydmi, ssif_trydmi, bool, 0);
MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the default scan of the interfaces identified via DMI (SMBIOS)"); MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the default scan of the interfaces identified via DMI (SMBIOS)");
...@@ -1582,6 +1586,10 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1582,6 +1586,10 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF; ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF;
} }
/* Some systems don't behave well if you enable alerts. */
if (alerts_broken)
goto found;
msg[0] = IPMI_NETFN_APP_REQUEST << 2; msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR; msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR;
...@@ -1787,7 +1795,7 @@ static unsigned short *ssif_address_list(void) ...@@ -1787,7 +1795,7 @@ static unsigned short *ssif_address_list(void)
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static struct acpi_device_id ssif_acpi_match[] = { static const struct acpi_device_id ssif_acpi_match[] = {
{ "IPI0001", 0 }, { "IPI0001", 0 },
{ }, { },
}; };
......
...@@ -115,6 +115,11 @@ struct ipmi_smi_handlers { ...@@ -115,6 +115,11 @@ struct ipmi_smi_handlers {
implement it. */ implement it. */
void (*set_need_watch)(void *send_info, bool enable); void (*set_need_watch)(void *send_info, bool enable);
/*
* Called when flushing all pending messages.
*/
void (*flush_messages)(void *send_info);
/* Called when the interface should go into "run to /* Called when the interface should go into "run to
completion" mode. If this call sets the value to true, the completion" mode. If this call sets the value to true, the
interface should make sure that all messages are flushed interface should make sure that all messages are flushed
...@@ -207,7 +212,7 @@ static inline int ipmi_demangle_device_id(const unsigned char *data, ...@@ -207,7 +212,7 @@ static inline int ipmi_demangle_device_id(const unsigned char *data,
upper layer until the start_processing() function in the handlers upper layer until the start_processing() function in the handlers
is called, and the lower layer must get the interface from that is called, and the lower layer must get the interface from that
call. */ call. */
int ipmi_register_smi(struct ipmi_smi_handlers *handlers, int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
void *send_info, void *send_info,
struct ipmi_device_id *device_id, struct ipmi_device_id *device_id,
struct device *dev, struct device *dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment