1
0
Fork 0

The big changes for IPMI that just went in had a few problems. These

have been in for-next for a while, each since about their creation
 date.  I forgot the bugzilla reference on the second one (ipmi_si: Fix
 oops with PCI devices) so I rebased to add that.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJaLo1KAAoJEGHzjJCRm/+B0HsP/joYHLSzoAESfihnx9JD1dn6
 JM8ZV8fu7e1ZpnrxyGj/dPLSBS1k8wsVKAEGrL5ETz4UOuwIR6/61wpzfyrQf/L5
 0ZBhpv8dAxpHvFZGGE1NCF4jNlo20K0i8YQk9lUxB3Nml3udUd+GUA/Li5d2vGo4
 e6xZyS15euNmHwnELaCguS9Vz79xusLmFvgicmi5l7+Y3X4Ul/sNL+pGySYUMqxU
 NvsH3fTDXJfRv2FCnJwn1sUGpPPPH0uYhaLKXNpekt0PgNNTlTzFWGnfRJrbD/+q
 OWXrfuqiwoCSRhfOXooI2vGAIZ+jjL/vBS9827EGjf0tWgTVnOx+wuDND15uZkxP
 LizUG0ZPcov0veDh1mExIBIU2sCGkZ+dlQeGLaVBQ4tNgbyJyWi5HiwvFc5r9s/e
 /ak0kkt9J54T4MgtEMBEEHSMatUixM8eXJ7K9ySZANP5vXlLmcpXVKBHEB42QWBN
 I1V5o1PVHxV8IrG/zOiWYBLYraWocEaNat/LzlbqGMfoVyb1gXpAI8Cbjphq1xOU
 49J5oY6L8MHNIu0VkEV9MtIEyLAM/V/nd8WQ3YpD/4UJnVoWcorBQWSC7NssWFm8
 5N4dq7kXSnUM4yA21PMogFCnRToO6nrK/ijxOkzWmPbDnvDDywQY/bnj7dAKFQri
 iQ67umU2z0+U4juY+Lls
 =3M4K
 -----END PGP SIGNATURE-----

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
hifive-unleashed-5.1
Linus Torvalds 2017-12-11 17:01:59 -08:00
commit bfb529ee79
3 changed files with 30 additions and 23 deletions

View File

@ -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 @@ out:
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,
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)
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)
* 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)
{ {
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)
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 @@ retry:
/* 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 @@ restart:
* 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,
/* 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)
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)
* 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 @@ out_err_remove_attrs:
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)
*/ */
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)
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);

View File

@ -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;

View File

@ -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);