aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/ipmi/ipmi_si.h5
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c154
-rw-r--r--drivers/char/ipmi/ipmi_si_sm.h4
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 @@ do_mod_timer:
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 @@ out_err:
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;