Blob Blame History Raw
From 4f3e8199c34dda46b6554191fe7a444dd6fa911f Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Tue, 12 Sep 2017 15:10:22 -0500
Subject: [PATCH] ipmi_si: Move irq setup handling into the io struct
Git-commit: 4f3e8199c34dda46b6554191fe7a444dd6fa911f
Patch-mainline: v4.15-rc1
References: FATE#326156

So the platform code can do it without having to access the
smi info, getting ready for pulling the platform handling
section to their own files.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/char/ipmi/ipmi_si.h      |   5 +
 drivers/char/ipmi/ipmi_si_intf.c | 154 +++++++++++++++----------------
 drivers/char/ipmi/ipmi_si_sm.h   |   4 +
 3 files changed, 82 insertions(+), 81 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
index a4d993b1fe66..e84651acd772 100644
--- a/drivers/char/ipmi/ipmi_si.h
+++ b/drivers/char/ipmi/ipmi_si.h
@@ -5,6 +5,7 @@
  * etc) to the base ipmi system interface code.
  */
 
+#include <linux/interrupt.h>
 #include "ipmi_si_sm.h"
 
 #define IPMI_IO_ADDR_SPACE  0
@@ -16,3 +17,7 @@
 struct smi_info;
 
 int ipmi_si_add_smi(struct smi_info *info);
+irqreturn_t ipmi_si_irq_handler(int irq, void *data);
+void ipmi_irq_start_cleanup(struct si_sm_io *io);
+int ipmi_std_irq_setup(struct si_sm_io *io);
+void ipmi_irq_finish_setup(struct si_sm_io *io);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 8cc101ea82d9..4b832b96d02b 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -175,8 +175,6 @@ struct smi_info {
 	struct si_sm_io io;
 	int (*io_setup)(struct smi_info *info);
 	void (*io_cleanup)(struct smi_info *info);
-	int (*irq_setup)(struct smi_info *info);
-	void (*irq_cleanup)(struct smi_info *info);
 	unsigned int io_size;
 
 	/*
@@ -1177,11 +1175,17 @@ static void smi_timeout(unsigned long data)
 	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
 }
 
-static irqreturn_t si_irq_handler(int irq, void *data)
+irqreturn_t ipmi_si_irq_handler(int irq, void *data)
 {
 	struct smi_info *smi_info = data;
 	unsigned long   flags;
 
+	if (smi_info->io.si_type == SI_BT)
+		/* We need to clear the IRQ flag for the BT interface. */
+		smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG,
+				     IPMI_BT_INTMASK_CLEAR_IRQ_BIT
+				     | IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
+
 	spin_lock_irqsave(&(smi_info->si_lock), flags);
 
 	smi_inc_stat(smi_info, interrupts);
@@ -1193,16 +1197,6 @@ static irqreturn_t si_irq_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t si_bt_irq_handler(int irq, void *data)
-{
-	struct smi_info *smi_info = data;
-	/* We need to clear the IRQ flag for the BT interface. */
-	smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG,
-			     IPMI_BT_INTMASK_CLEAR_IRQ_BIT
-			     | IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
-	return si_irq_handler(irq, data);
-}
-
 static int smi_start_processing(void       *send_info,
 				ipmi_smi_t intf)
 {
@@ -1216,8 +1210,10 @@ static int smi_start_processing(void       *send_info,
 	smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
 
 	/* Try to claim any interrupts. */
-	if (new_smi->irq_setup)
-		new_smi->irq_setup(new_smi);
+	if (new_smi->io.irq_setup) {
+		new_smi->io.irq_handler_data = new_smi;
+		new_smi->io.irq_setup(&new_smi->io);
+	}
 
 	/*
 	 * Check if the user forcefully enabled the daemon.
@@ -1400,46 +1396,48 @@ MODULE_PARM_DESC(kipmid_max_busy_us,
 		 " sleeping. 0 (default) means to wait forever. Set to 100-500"
 		 " if kipmid is using up a lot of CPU time.");
 
+void ipmi_irq_finish_setup(struct si_sm_io *io)
+{
+	if (io->si_type == SI_BT)
+		/* Enable the interrupt in the BT interface. */
+		io->outputb(io, IPMI_BT_INTMASK_REG,
+			    IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
+}
 
-static void std_irq_cleanup(struct smi_info *info)
+void ipmi_irq_start_cleanup(struct si_sm_io *io)
 {
-	if (info->io.si_type == SI_BT)
+	if (io->si_type == SI_BT)
 		/* Disable the interrupt in the BT interface. */
-		info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0);
-	free_irq(info->io.irq, info);
+		io->outputb(io, IPMI_BT_INTMASK_REG, 0);
+}
+
+static void std_irq_cleanup(struct si_sm_io *io)
+{
+	ipmi_irq_start_cleanup(io);
+	free_irq(io->irq, io->irq_handler_data);
 }
 
-static int std_irq_setup(struct smi_info *info)
+int ipmi_std_irq_setup(struct si_sm_io *io)
 {
 	int rv;
 
-	if (!info->io.irq)
+	if (!io->irq)
 		return 0;
 
-	if (info->io.si_type == SI_BT) {
-		rv = request_irq(info->io.irq,
-				 si_bt_irq_handler,
-				 IRQF_SHARED,
-				 DEVICE_NAME,
-				 info);
-		if (!rv)
-			/* Enable the interrupt in the BT interface. */
-			info->io.outputb(&info->io, IPMI_BT_INTMASK_REG,
-					 IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
-	} else
-		rv = request_irq(info->io.irq,
-				 si_irq_handler,
-				 IRQF_SHARED,
-				 DEVICE_NAME,
-				 info);
+	rv = request_irq(io->irq,
+			 ipmi_si_irq_handler,
+			 IRQF_SHARED,
+			 DEVICE_NAME,
+			 io->irq_handler_data);
 	if (rv) {
-		dev_warn(info->io.dev, "%s unable to claim interrupt %d,"
+		dev_warn(io->dev, "%s unable to claim interrupt %d,"
 			 " running polled\n",
-			 DEVICE_NAME, info->io.irq);
-		info->io.irq = 0;
+			 DEVICE_NAME, io->irq);
+		io->irq = 0;
 	} else {
-		info->irq_cleanup = std_irq_cleanup;
-		dev_info(info->io.dev, "Using irq %d\n", info->io.irq);
+		io->irq_cleanup = std_irq_cleanup;
+		ipmi_irq_finish_setup(io);
+		dev_info(io->dev, "Using irq %d\n", io->irq);
 	}
 
 	return rv;
@@ -1920,7 +1918,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 			info->io.regshift = regshift;
 			info->io.irq = irq;
 			if (info->io.irq)
-				info->irq_setup = std_irq_setup;
+				info->io.irq_setup = ipmi_std_irq_setup;
 			info->io.slave_addr = ipmb;
 
 			rv = ipmi_si_add_smi(info);
@@ -2014,7 +2012,7 @@ static int hardcode_find_bmc(void)
 		info->io.regshift = regshifts[i];
 		info->io.irq = irqs[i];
 		if (info->io.irq)
-			info->irq_setup = std_irq_setup;
+			info->io.irq_setup = ipmi_std_irq_setup;
 		info->io.slave_addr = slave_addrs[i];
 
 		if (!ipmi_si_add_smi(info)) {
@@ -2043,49 +2041,43 @@ static int acpi_failure;
 static u32 ipmi_acpi_gpe(acpi_handle gpe_device,
 	u32 gpe_number, void *context)
 {
-	struct smi_info *smi_info = context;
-	unsigned long   flags;
-
-	spin_lock_irqsave(&(smi_info->si_lock), flags);
-
-	smi_inc_stat(smi_info, interrupts);
-
-	debug_timestamp("ACPI_GPE");
-
-	smi_event_handler(smi_info, 0);
-	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+	struct si_sm_io *io = context;
 
+	ipmi_si_irq_handler(io->irq, io->irq_handler_data);
 	return ACPI_INTERRUPT_HANDLED;
 }
 
-static void acpi_gpe_irq_cleanup(struct smi_info *info)
+static void acpi_gpe_irq_cleanup(struct si_sm_io *io)
 {
-	if (!info->io.irq)
+	if (!io->irq)
 		return;
 
-	acpi_remove_gpe_handler(NULL, info->io.irq, &ipmi_acpi_gpe);
+	ipmi_irq_start_cleanup(io);
+	acpi_remove_gpe_handler(NULL, io->irq, &ipmi_acpi_gpe);
 }
 
-static int acpi_gpe_irq_setup(struct smi_info *info)
+static int acpi_gpe_irq_setup(struct si_sm_io *io)
 {
 	acpi_status status;
 
-	if (!info->io.irq)
+	if (!io->irq)
 		return 0;
 
 	status = acpi_install_gpe_handler(NULL,
-					  info->io.irq,
+					  io->irq,
 					  ACPI_GPE_LEVEL_TRIGGERED,
 					  &ipmi_acpi_gpe,
-					  info);
+					  io);
 	if (status != AE_OK) {
-		dev_warn(info->io.dev, "%s unable to claim ACPI GPE %d,"
-			 " running polled\n", DEVICE_NAME, info->io.irq);
-		info->io.irq = 0;
+		dev_warn(io->dev,
+			 "Unable to claim ACPI GPE %d, running polled\n",
+			 io->irq);
+		io->irq = 0;
 		return -EINVAL;
 	} else {
-		info->irq_cleanup = acpi_gpe_irq_cleanup;
-		dev_info(info->io.dev, "Using ACPI GPE %d\n", info->io.irq);
+		io->irq_cleanup = acpi_gpe_irq_cleanup;
+		ipmi_irq_finish_setup(io);
+		dev_info(io->dev, "Using ACPI GPE %d\n", io->irq);
 		return 0;
 	}
 }
@@ -2179,15 +2171,15 @@ static int try_init_spmi(struct SPMITable *spmi)
 	if (spmi->InterruptType & 1) {
 		/* We've got a GPE interrupt. */
 		info->io.irq = spmi->GPE;
-		info->irq_setup = acpi_gpe_irq_setup;
+		info->io.irq_setup = acpi_gpe_irq_setup;
 	} else if (spmi->InterruptType & 2) {
 		/* We've got an APIC/SAPIC interrupt. */
 		info->io.irq = spmi->GlobalSystemInterrupt;
-		info->irq_setup = std_irq_setup;
+		info->io.irq_setup = ipmi_std_irq_setup;
 	} else {
 		/* Use the default interrupt setting. */
 		info->io.irq = 0;
-		info->irq_setup = NULL;
+		info->io.irq_setup = NULL;
 	}
 
 	if (spmi->addr.bit_width) {
@@ -2342,7 +2334,7 @@ static int dmi_ipmi_probe(struct platform_device *pdev)
 
 	info->io.irq = platform_get_irq(pdev, 0);
 	if (info->io.irq > 0)
-		info->irq_setup = std_irq_setup;
+		info->io.irq_setup = ipmi_std_irq_setup;
 	else
 		info->io.irq = 0;
 
@@ -2479,7 +2471,7 @@ static int ipmi_pci_probe(struct pci_dev *pdev,
 
 	info->io.irq = pdev->irq;
 	if (info->io.irq)
-		info->irq_setup = std_irq_setup;
+		info->io.irq_setup = ipmi_std_irq_setup;
 
 	info->io.dev = &pdev->dev;
 	pci_set_drvdata(pdev, info);
@@ -2583,7 +2575,7 @@ static int of_ipmi_probe(struct platform_device *pdev)
 
 	info->io.si_type	= (enum si_type) match->data;
 	info->io.addr_source	= SI_DEVICETREE;
-	info->io.irq_setup	= std_irq_setup;
+	info->io.irq_setup	= ipmi_std_irq_setup;
 
 	if (resource.flags & IORESOURCE_IO) {
 		info->io_setup		= port_setup;
@@ -2715,13 +2707,13 @@ static int acpi_ipmi_probe(struct platform_device *pdev)
 	status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
 	if (ACPI_SUCCESS(status)) {
 		info->io.irq = tmp;
-		info->irq_setup = acpi_gpe_irq_setup;
+		info->io.irq_setup = acpi_gpe_irq_setup;
 	} else {
 		int irq = platform_get_irq(pdev, 0);
 
 		if (irq > 0) {
 			info->io.irq = irq;
-			info->irq_setup = std_irq_setup;
+			info->io.irq_setup = ipmi_std_irq_setup;
 		}
 	}
 
@@ -2809,7 +2801,7 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev)
 	info->io.regspacing	= 1;
 	info->io.regshift	= 0;
 	info->io.irq		= 0; /* no interrupt */
-	info->irq_setup		= NULL;
+	info->io.irq_setup	= NULL;
 	info->io.dev		= &dev->dev;
 
 	dev_dbg(&dev->dev, "addr 0x%lx\n", info->io.addr_data);
@@ -3665,9 +3657,9 @@ static int try_smi_init(struct smi_info *new_smi)
 		ipmi_unregister_smi(intf);
 	}
 
-	if (new_smi->irq_cleanup) {
-		new_smi->irq_cleanup(new_smi);
-		new_smi->irq_cleanup = NULL;
+	if (new_smi->io.irq_cleanup) {
+		new_smi->io.irq_cleanup(&new_smi->io);
+		new_smi->io.irq_cleanup = NULL;
 	}
 
 	/*
@@ -3842,8 +3834,8 @@ static void cleanup_one_si(struct smi_info *to_clean)
 	 * Make sure that interrupts, the timer and the thread are
 	 * stopped and will not run again.
 	 */
-	if (to_clean->irq_cleanup)
-		to_clean->irq_cleanup(to_clean);
+	if (to_clean->io.irq_cleanup)
+		to_clean->io.irq_cleanup(&to_clean->io);
 	wait_for_timer_and_thread(to_clean);
 
 	/*
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
index ffbf67f630a9..bf3f50cede44 100644
--- a/drivers/char/ipmi/ipmi_si_sm.h
+++ b/drivers/char/ipmi/ipmi_si_sm.h
@@ -72,6 +72,10 @@ struct si_sm_io {
 	void *addr_source_data;
 
 	int irq;
+	int (*irq_setup)(struct si_sm_io *io);
+	void *irq_handler_data;
+	void (*irq_cleanup)(struct si_sm_io *io);
+
 	u8 slave_addr;
 	enum si_type si_type;
 	struct device *dev;
-- 
2.19.2