Commit bfb529ee authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-4.15-2' of git://github.com/cminyard/linux-ipmi

Pull IPMI fixes from Corey Minyard.

* tag 'for-linus-4.15-2' of git://github.com/cminyard/linux-ipmi:
  ipmi_si: fix crash on parisc
  ipmi_si: Fix oops with PCI devices
  ipmi: Stop timers before cleaning up the module
parents 916b20e0 51614b26
...@@ -199,6 +199,9 @@ struct smi_info { ...@@ -199,6 +199,9 @@ struct smi_info {
/* The timer for this si. */ /* The timer for this si. */
struct timer_list si_timer; struct timer_list si_timer;
/* This flag is set, if the timer can be set */
bool timer_can_start;
/* This flag is set, if the timer is running (timer_pending() isn't enough) */ /* This flag is set, if the timer is running (timer_pending() isn't enough) */
bool timer_running; bool timer_running;
...@@ -355,6 +358,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) ...@@ -355,6 +358,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
{ {
if (!smi_info->timer_can_start)
return;
smi_info->last_timeout_jiffies = jiffies; smi_info->last_timeout_jiffies = jiffies;
mod_timer(&smi_info->si_timer, new_val); mod_timer(&smi_info->si_timer, new_val);
smi_info->timer_running = true; smi_info->timer_running = true;
...@@ -374,21 +379,18 @@ static void start_new_msg(struct smi_info *smi_info, unsigned char *msg, ...@@ -374,21 +379,18 @@ static void start_new_msg(struct smi_info *smi_info, unsigned char *msg,
smi_info->handlers->start_transaction(smi_info->si_sm, msg, size); smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
} }
static void start_check_enables(struct smi_info *smi_info, bool start_timer) static void start_check_enables(struct smi_info *smi_info)
{ {
unsigned char msg[2]; unsigned char msg[2];
msg[0] = (IPMI_NETFN_APP_REQUEST << 2); msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
if (start_timer)
start_new_msg(smi_info, msg, 2); start_new_msg(smi_info, msg, 2);
else
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
smi_info->si_state = SI_CHECKING_ENABLES; smi_info->si_state = SI_CHECKING_ENABLES;
} }
static void start_clear_flags(struct smi_info *smi_info, bool start_timer) static void start_clear_flags(struct smi_info *smi_info)
{ {
unsigned char msg[3]; unsigned char msg[3];
...@@ -397,10 +399,7 @@ static void start_clear_flags(struct smi_info *smi_info, bool start_timer) ...@@ -397,10 +399,7 @@ static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD; msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
msg[2] = WDT_PRE_TIMEOUT_INT; msg[2] = WDT_PRE_TIMEOUT_INT;
if (start_timer)
start_new_msg(smi_info, msg, 3); start_new_msg(smi_info, msg, 3);
else
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
smi_info->si_state = SI_CLEARING_FLAGS; smi_info->si_state = SI_CLEARING_FLAGS;
} }
...@@ -435,11 +434,11 @@ static void start_getting_events(struct smi_info *smi_info) ...@@ -435,11 +434,11 @@ static void start_getting_events(struct smi_info *smi_info)
* Note that we cannot just use disable_irq(), since the interrupt may * Note that we cannot just use disable_irq(), since the interrupt may
* be shared. * be shared.
*/ */
static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer) static inline bool disable_si_irq(struct smi_info *smi_info)
{ {
if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) { if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = true; smi_info->interrupt_disabled = true;
start_check_enables(smi_info, start_timer); start_check_enables(smi_info);
return true; return true;
} }
return false; return false;
...@@ -449,7 +448,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info) ...@@ -449,7 +448,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info)
{ {
if ((smi_info->io.irq) && (smi_info->interrupt_disabled)) { if ((smi_info->io.irq) && (smi_info->interrupt_disabled)) {
smi_info->interrupt_disabled = false; smi_info->interrupt_disabled = false;
start_check_enables(smi_info, true); start_check_enables(smi_info);
return true; return true;
} }
return false; return false;
...@@ -467,7 +466,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info) ...@@ -467,7 +466,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info)
msg = ipmi_alloc_smi_msg(); msg = ipmi_alloc_smi_msg();
if (!msg) { if (!msg) {
if (!disable_si_irq(smi_info, true)) if (!disable_si_irq(smi_info))
smi_info->si_state = SI_NORMAL; smi_info->si_state = SI_NORMAL;
} else if (enable_si_irq(smi_info)) { } else if (enable_si_irq(smi_info)) {
ipmi_free_smi_msg(msg); ipmi_free_smi_msg(msg);
...@@ -483,7 +482,7 @@ static void handle_flags(struct smi_info *smi_info) ...@@ -483,7 +482,7 @@ static void handle_flags(struct smi_info *smi_info)
/* Watchdog pre-timeout */ /* Watchdog pre-timeout */
smi_inc_stat(smi_info, watchdog_pretimeouts); smi_inc_stat(smi_info, watchdog_pretimeouts);
start_clear_flags(smi_info, true); start_clear_flags(smi_info);
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
if (smi_info->intf) if (smi_info->intf)
ipmi_smi_watchdog_pretimeout(smi_info->intf); ipmi_smi_watchdog_pretimeout(smi_info->intf);
...@@ -866,7 +865,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, ...@@ -866,7 +865,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
* disable and messages disabled. * disable and messages disabled.
*/ */
if (smi_info->supports_event_msg_buff || smi_info->io.irq) { if (smi_info->supports_event_msg_buff || smi_info->io.irq) {
start_check_enables(smi_info, true); start_check_enables(smi_info);
} else { } else {
smi_info->curr_msg = alloc_msg_handle_irq(smi_info); smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
if (!smi_info->curr_msg) if (!smi_info->curr_msg)
...@@ -1167,6 +1166,7 @@ static int smi_start_processing(void *send_info, ...@@ -1167,6 +1166,7 @@ static int smi_start_processing(void *send_info,
/* Set up the timer that drives the interface. */ /* Set up the timer that drives the interface. */
timer_setup(&new_smi->si_timer, smi_timeout, 0); timer_setup(&new_smi->si_timer, smi_timeout, 0);
new_smi->timer_can_start = true;
smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES); smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
/* Try to claim any interrupts. */ /* Try to claim any interrupts. */
...@@ -1936,10 +1936,12 @@ static void check_for_broken_irqs(struct smi_info *smi_info) ...@@ -1936,10 +1936,12 @@ static void check_for_broken_irqs(struct smi_info *smi_info)
check_set_rcv_irq(smi_info); check_set_rcv_irq(smi_info);
} }
static inline void wait_for_timer_and_thread(struct smi_info *smi_info) static inline void stop_timer_and_thread(struct smi_info *smi_info)
{ {
if (smi_info->thread != NULL) if (smi_info->thread != NULL)
kthread_stop(smi_info->thread); kthread_stop(smi_info->thread);
smi_info->timer_can_start = false;
if (smi_info->timer_running) if (smi_info->timer_running)
del_timer_sync(&smi_info->si_timer); del_timer_sync(&smi_info->si_timer);
} }
...@@ -2152,7 +2154,7 @@ static int try_smi_init(struct smi_info *new_smi) ...@@ -2152,7 +2154,7 @@ static int try_smi_init(struct smi_info *new_smi)
* Start clearing the flags before we enable interrupts or the * Start clearing the flags before we enable interrupts or the
* timer to avoid racing with the timer. * timer to avoid racing with the timer.
*/ */
start_clear_flags(new_smi, false); start_clear_flags(new_smi);
/* /*
* IRQ is defined to be set when non-zero. req_events will * IRQ is defined to be set when non-zero. req_events will
...@@ -2238,7 +2240,7 @@ static int try_smi_init(struct smi_info *new_smi) ...@@ -2238,7 +2240,7 @@ static int try_smi_init(struct smi_info *new_smi)
dev_set_drvdata(new_smi->io.dev, NULL); dev_set_drvdata(new_smi->io.dev, NULL);
out_err_stop_timer: out_err_stop_timer:
wait_for_timer_and_thread(new_smi); stop_timer_and_thread(new_smi);
out_err: out_err:
new_smi->interrupt_disabled = true; new_smi->interrupt_disabled = true;
...@@ -2388,7 +2390,7 @@ static void cleanup_one_si(struct smi_info *to_clean) ...@@ -2388,7 +2390,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
*/ */
if (to_clean->io.irq_cleanup) if (to_clean->io.irq_cleanup)
to_clean->io.irq_cleanup(&to_clean->io); to_clean->io.irq_cleanup(&to_clean->io);
wait_for_timer_and_thread(to_clean); stop_timer_and_thread(to_clean);
/* /*
* Timeouts are stopped, now make sure the interrupts are off * Timeouts are stopped, now make sure the interrupts are off
...@@ -2400,7 +2402,7 @@ static void cleanup_one_si(struct smi_info *to_clean) ...@@ -2400,7 +2402,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
} }
if (to_clean->handlers) if (to_clean->handlers)
disable_si_irq(to_clean, false); disable_si_irq(to_clean);
while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
poll(to_clean); poll(to_clean);
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
......
...@@ -10,6 +10,8 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev) ...@@ -10,6 +10,8 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev)
{ {
struct si_sm_io io; struct si_sm_io io;
memset(&io, 0, sizeof(io));
io.si_type = SI_KCS; io.si_type = SI_KCS;
io.addr_source = SI_DEVICETREE; io.addr_source = SI_DEVICETREE;
io.addr_type = IPMI_MEM_ADDR_SPACE; io.addr_type = IPMI_MEM_ADDR_SPACE;
......
...@@ -103,10 +103,13 @@ static int ipmi_pci_probe(struct pci_dev *pdev, ...@@ -103,10 +103,13 @@ static int ipmi_pci_probe(struct pci_dev *pdev,
io.addr_source_cleanup = ipmi_pci_cleanup; io.addr_source_cleanup = ipmi_pci_cleanup;
io.addr_source_data = pdev; io.addr_source_data = pdev;
if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
io.addr_type = IPMI_IO_ADDR_SPACE; io.addr_type = IPMI_IO_ADDR_SPACE;
else io.io_setup = ipmi_si_port_setup;
} else {
io.addr_type = IPMI_MEM_ADDR_SPACE; io.addr_type = IPMI_MEM_ADDR_SPACE;
io.io_setup = ipmi_si_mem_setup;
}
io.addr_data = pci_resource_start(pdev, 0); io.addr_data = pci_resource_start(pdev, 0);
io.regspacing = ipmi_pci_probe_regspacing(&io); io.regspacing = ipmi_pci_probe_regspacing(&io);
......
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