From: Corey Minyard Enable interrupts for a BT interface. There is a specific register that needs to be set up to enable interrupts that also must be modified to clear the irq. Also, don't reset the BMC on a BT interface. That's probably not a good idea as the BMC may be performing other important functions and a reset should only be a last resort. Also, that register is also used to enable/disable interrupts to the BT; modifying it may screw up the interrupts. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton --- drivers/char/ipmi/ipmi_bt_sm.c | 1 drivers/char/ipmi/ipmi_si_intf.c | 40 ++++++++++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff -puN drivers/char/ipmi/ipmi_bt_sm.c~ipmi-enable-interrupts-on-the-bt-driver drivers/char/ipmi/ipmi_bt_sm.c --- 25/drivers/char/ipmi/ipmi_bt_sm.c~ipmi-enable-interrupts-on-the-bt-driver 2005-04-29 18:27:12.600505864 -0700 +++ 25-akpm/drivers/char/ipmi/ipmi_bt_sm.c 2005-04-29 18:27:12.616503432 -0700 @@ -235,7 +235,6 @@ static void reset_flags(struct si_sm_dat if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY); BT_CONTROL(BT_CLR_WR_PTR); BT_CONTROL(BT_SMS_ATN); - BT_INTMASK_W(BT_BMC_HWRST); #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION if (BT_STATUS & BT_B2H_ATN) { int i; diff -puN drivers/char/ipmi/ipmi_si_intf.c~ipmi-enable-interrupts-on-the-bt-driver drivers/char/ipmi/ipmi_si_intf.c --- 25/drivers/char/ipmi/ipmi_si_intf.c~ipmi-enable-interrupts-on-the-bt-driver 2005-04-29 18:27:12.601505712 -0700 +++ 25-akpm/drivers/char/ipmi/ipmi_si_intf.c 2005-04-29 18:27:12.616503432 -0700 @@ -100,6 +100,11 @@ enum si_intf_state { /* FIXME - add watchdog stuff. */ }; +/* Some BT-specific defines we need here. */ +#define IPMI_BT_INTMASK_REG 2 +#define IPMI_BT_INTMASK_CLEAR_IRQ_BIT 2 +#define IPMI_BT_INTMASK_ENABLE_IRQ_BIT 1 + enum si_type { SI_KCS, SI_SMIC, SI_BT }; @@ -875,6 +880,17 @@ static irqreturn_t si_irq_handler(int ir return IRQ_HANDLED; } +static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs) +{ + 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, regs); +} + + static struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, @@ -1001,11 +1017,22 @@ static int std_irq_setup(struct smi_info if (!info->irq) return 0; - rv = request_irq(info->irq, - si_irq_handler, - SA_INTERRUPT, - DEVICE_NAME, - info); + if (info->si_type == SI_BT) { + rv = request_irq(info->irq, + si_bt_irq_handler, + SA_INTERRUPT, + 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->irq, + si_irq_handler, + SA_INTERRUPT, + DEVICE_NAME, + info); if (rv) { printk(KERN_WARNING "ipmi_si: %s unable to claim interrupt %d," @@ -1024,6 +1051,9 @@ static void std_irq_cleanup(struct smi_i if (!info->irq) return; + if (info->si_type == SI_BT) + /* Disable the interrupt in the BT interface. */ + info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, 0); free_irq(info->irq, info); } _