aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2014-11-20 08:19:44 -0500
committerCorey Minyard <cminyard@mvista.com>2014-12-11 16:04:14 -0500
commit95c97b5941542a4dedb22649adea98e25a88923e (patch)
tree26fcf164fc4c31728ab2d41af94bfb25dacce9b0 /drivers/char
parenta8df150c5de4b2a542660e7b3727fddfce2e015b (diff)
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)
536#define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \ 536#define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \
537 IPMI_BMC_EVT_MSG_INTR) 537 IPMI_BMC_EVT_MSG_INTR)
538 538
539static u8 current_global_enables(struct smi_info *smi_info, u8 base) 539static u8 current_global_enables(struct smi_info *smi_info, u8 base,
540 bool *irq_on)
540{ 541{
541 u8 enables = 0; 542 u8 enables = 0;
542 543
@@ -557,9 +558,27 @@ static u8 current_global_enables(struct smi_info *smi_info, u8 base)
557 else 558 else
558 enables &= ~IPMI_BMC_EVT_MSG_INTR; 559 enables &= ~IPMI_BMC_EVT_MSG_INTR;
559 560
561 *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR);
562
560 return enables; 563 return enables;
561} 564}
562 565
566static void check_bt_irq(struct smi_info *smi_info, bool irq_on)
567{
568 u8 irqstate = smi_info->io.inputb(&smi_info->io, IPMI_BT_INTMASK_REG);
569
570 irqstate &= IPMI_BT_INTMASK_ENABLE_IRQ_BIT;
571
572 if ((bool)irqstate == irq_on)
573 return;
574
575 if (irq_on)
576 smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG,
577 IPMI_BT_INTMASK_ENABLE_IRQ_BIT);
578 else
579 smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG, 0);
580}
581
563static void handle_transaction_done(struct smi_info *smi_info) 582static void handle_transaction_done(struct smi_info *smi_info)
564{ 583{
565 struct ipmi_smi_msg *msg; 584 struct ipmi_smi_msg *msg;
@@ -708,6 +727,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
708 { 727 {
709 unsigned char msg[4]; 728 unsigned char msg[4];
710 u8 enables; 729 u8 enables;
730 bool irq_on;
711 731
712 /* We got the flags from the SMI, now handle them. */ 732 /* We got the flags from the SMI, now handle them. */
713 smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 733 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)
719 smi_info->si_state = SI_NORMAL; 739 smi_info->si_state = SI_NORMAL;
720 break; 740 break;
721 } 741 }
722 enables = current_global_enables(smi_info, 0); 742 enables = current_global_enables(smi_info, 0, &irq_on);
743 if (smi_info->si_type == SI_BT)
744 /* BT has its own interrupt enable bit. */
745 check_bt_irq(smi_info, irq_on);
723 if (enables != (msg[3] & GLOBAL_ENABLES_MASK)) { 746 if (enables != (msg[3] & GLOBAL_ENABLES_MASK)) {
724 /* Enables are not correct, fix them. */ 747 /* Enables are not correct, fix them. */
725 msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 748 msg[0] = (IPMI_NETFN_APP_REQUEST << 2);