summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2014-11-20 14:19:44 +0100
committerCorey Minyard <cminyard@mvista.com>2014-12-11 22:04:14 +0100
commit95c97b5941542a4dedb22649adea98e25a88923e (patch)
tree26fcf164fc4c31728ab2d41af94bfb25dacce9b0 /drivers/char
parentipmi: Fix attention handling for system interfaces (diff)
downloadlinux-95c97b5941542a4dedb22649adea98e25a88923e.tar.xz
linux-95c97b5941542a4dedb22649adea98e25a88923e.zip
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')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c27
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);