Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfb529ee authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+23 −21
Original line number Diff line number Diff line
@@ -199,6 +199,9 @@ struct smi_info {
	/* The timer for this si. */
	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) */
	bool		    timer_running;

@@ -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)
{
	if (!smi_info->timer_can_start)
		return;
	smi_info->last_timeout_jiffies = jiffies;
	mod_timer(&smi_info->si_timer, new_val);
	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);
}

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

	msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
	msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;

	if (start_timer)
	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;
}

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

@@ -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[2] = WDT_PRE_TIMEOUT_INT;

	if (start_timer)
	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;
}

@@ -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
 * 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)) {
		smi_info->interrupt_disabled = true;
		start_check_enables(smi_info, start_timer);
		start_check_enables(smi_info);
		return true;
	}
	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)) {
		smi_info->interrupt_disabled = false;
		start_check_enables(smi_info, true);
		start_check_enables(smi_info);
		return true;
	}
	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();
	if (!msg) {
		if (!disable_si_irq(smi_info, true))
		if (!disable_si_irq(smi_info))
			smi_info->si_state = SI_NORMAL;
	} else if (enable_si_irq(smi_info)) {
		ipmi_free_smi_msg(msg);
@@ -483,7 +482,7 @@ static void handle_flags(struct smi_info *smi_info)
		/* Watchdog pre-timeout */
		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;
		if (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,
		 * disable and messages disabled.
		 */
		if (smi_info->supports_event_msg_buff || smi_info->io.irq) {
			start_check_enables(smi_info, true);
			start_check_enables(smi_info);
		} else {
			smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
			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. */
	timer_setup(&new_smi->si_timer, smi_timeout, 0);
	new_smi->timer_can_start = true;
	smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);

	/* 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);
}

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)
		kthread_stop(smi_info->thread);

	smi_info->timer_can_start = false;
	if (smi_info->timer_running)
		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
	 * 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
@@ -2238,7 +2240,7 @@ static int try_smi_init(struct smi_info *new_smi)
	dev_set_drvdata(new_smi->io.dev, NULL);

out_err_stop_timer:
	wait_for_timer_and_thread(new_smi);
	stop_timer_and_thread(new_smi);

out_err:
	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)
		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
@@ -2400,7 +2402,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
		schedule_timeout_uninterruptible(1);
	}
	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)) {
		poll(to_clean);
		schedule_timeout_uninterruptible(1);
+2 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev)
{
	struct si_sm_io io;

	memset(&io, 0, sizeof(io));

	io.si_type	= SI_KCS;
	io.addr_source	= SI_DEVICETREE;
	io.addr_type	= IPMI_MEM_ADDR_SPACE;
+5 −2
Original line number Diff line number Diff line
@@ -103,10 +103,13 @@ static int ipmi_pci_probe(struct pci_dev *pdev,
	io.addr_source_cleanup = ipmi_pci_cleanup;
	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;
	else
		io.io_setup = ipmi_si_port_setup;
	} else {
		io.addr_type = IPMI_MEM_ADDR_SPACE;
		io.io_setup = ipmi_si_mem_setup;
	}
	io.addr_data = pci_resource_start(pdev, 0);

	io.regspacing = ipmi_pci_probe_regspacing(&io);