forked from Minki/linux
[PATCH] ipmi: enable interrupts on the BT driver
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 <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
ec26d79f4f
commit
9dbf68f97d
|
@ -235,7 +235,6 @@ static void reset_flags(struct si_sm_data *bt)
|
||||||
if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
|
if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
|
||||||
BT_CONTROL(BT_CLR_WR_PTR);
|
BT_CONTROL(BT_CLR_WR_PTR);
|
||||||
BT_CONTROL(BT_SMS_ATN);
|
BT_CONTROL(BT_SMS_ATN);
|
||||||
BT_INTMASK_W(BT_BMC_HWRST);
|
|
||||||
#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
|
#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
|
||||||
if (BT_STATUS & BT_B2H_ATN) {
|
if (BT_STATUS & BT_B2H_ATN) {
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -100,6 +100,11 @@ enum si_intf_state {
|
||||||
/* FIXME - add watchdog stuff. */
|
/* 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 {
|
enum si_type {
|
||||||
SI_KCS, SI_SMIC, SI_BT
|
SI_KCS, SI_SMIC, SI_BT
|
||||||
};
|
};
|
||||||
|
@ -875,6 +880,17 @@ static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs)
|
||||||
return IRQ_HANDLED;
|
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 =
|
static struct ipmi_smi_handlers handlers =
|
||||||
{
|
{
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -1001,11 +1017,22 @@ static int std_irq_setup(struct smi_info *info)
|
||||||
if (!info->irq)
|
if (!info->irq)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rv = request_irq(info->irq,
|
if (info->si_type == SI_BT) {
|
||||||
si_irq_handler,
|
rv = request_irq(info->irq,
|
||||||
SA_INTERRUPT,
|
si_bt_irq_handler,
|
||||||
DEVICE_NAME,
|
SA_INTERRUPT,
|
||||||
info);
|
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) {
|
if (rv) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"ipmi_si: %s unable to claim interrupt %d,"
|
"ipmi_si: %s unable to claim interrupt %d,"
|
||||||
|
@ -1024,6 +1051,9 @@ static void std_irq_cleanup(struct smi_info *info)
|
||||||
if (!info->irq)
|
if (!info->irq)
|
||||||
return;
|
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);
|
free_irq(info->irq, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user