diff options
author | Corey Minyard <cminyard@mvista.com> | 2014-11-20 07:19:44 -0600 |
---|---|---|
committer | Corey Minyard <cminyard@mvista.com> | 2014-12-11 15:04:14 -0600 |
commit | 95c97b5941542a4dedb22649adea98e25a88923e (patch) | |
tree | 26fcf164fc4c31728ab2d41af94bfb25dacce9b0 /drivers/char/ipmi | |
parent | a8df150c5de4b2a542660e7b3727fddfce2e015b (diff) | |
download | linux-95c97b5941542a4dedb22649adea98e25a88923e.tar.gz linux-95c97b5941542a4dedb22649adea98e25a88923e.tar.xz |
ipmi: Check the BT interrupt enable periodically
On a reset, the BMC may reset the BT enable in the processor
registers (different than the global enables in the BMC). Check
it periodically and fix it if necessary.
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Tested-by: Tony Rex <tony.rex@ericsson.com>
Tested-by: Magnus Johansson E <magnus.e.johansson@ericsson.com>
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4a894afc5a2e..90c7fdf95419 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -536,7 +536,8 @@ static void handle_flags(struct smi_info *smi_info) #define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \ IPMI_BMC_EVT_MSG_INTR) -static u8 current_global_enables(struct smi_info *smi_info, u8 base) +static u8 current_global_enables(struct smi_info *smi_info, u8 base, + bool *irq_on) { u8 enables = 0; @@ -557,9 +558,27 @@ static u8 current_global_enables(struct smi_info *smi_info, u8 base) else enables &= ~IPMI_BMC_EVT_MSG_INTR; + *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR); + return enables; } +static void check_bt_irq(struct smi_info *smi_info, bool irq_on) +{ + u8 irqstate = smi_info->io.inputb(&smi_info->io, IPMI_BT_INTMASK_REG); + + irqstate &= IPMI_BT_INTMASK_ENABLE_IRQ_BIT; + + if ((bool)irqstate == irq_on) + return; + + if (irq_on) + smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG, + IPMI_BT_INTMASK_ENABLE_IRQ_BIT); + else + smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG, 0); +} + static void handle_transaction_done(struct smi_info *smi_info) { struct ipmi_smi_msg *msg; @@ -708,6 +727,7 @@ static void handle_transaction_done(struct smi_info *smi_info) { unsigned char msg[4]; u8 enables; + bool irq_on; /* We got the flags from the SMI, now handle them. */ smi_info->handlers->get_result(smi_info->si_sm, msg, 4); @@ -719,7 +739,10 @@ static void handle_transaction_done(struct smi_info *smi_info) smi_info->si_state = SI_NORMAL; break; } - enables = current_global_enables(smi_info, 0); + enables = current_global_enables(smi_info, 0, &irq_on); + if (smi_info->si_type == SI_BT) + /* BT has its own interrupt enable bit. */ + check_bt_irq(smi_info, irq_on); if (enables != (msg[3] & GLOBAL_ENABLES_MASK)) { /* Enables are not correct, fix them. */ msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |