diff --git a/kestrel/src/kestrel.c b/kestrel/src/kestrel.c index 7f2b73be00d468e1a6f246462d564420621d48c7..64179be22ea2cef69113fcad59b1e83fcb9df347 100644 --- a/kestrel/src/kestrel.c +++ b/kestrel/src/kestrel.c @@ -792,6 +792,11 @@ void lpc_slave_isr(void) } write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_IPMI_BT_STATUS, dword); + // Disable IPMI BT IRQ + dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1); + dword &= ~((1 & AQUILA_LPC_CTL_EN_IPMI_BT_IRQ_MASK) << AQUILA_LPC_CTL_EN_IPMI_BT_IRQ_SHIFT); + write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1, dword); + // Clear H2B_ATN dword = 0; dword |= (1 << IPMI_BT_CTL_H2B_ATN_SHIFT); @@ -1231,7 +1236,7 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) uint32_t dword; static uint8_t unhandled_ipmi_command; - volatile ipmi_response_message_t *response_ptr; + ipmi_response_message_t *response_ptr; static ipmi_response_message_t response; static uint8_t request_netfn; static uint8_t request_lun; @@ -1242,6 +1247,15 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) int i; + int irqs_locked = 0; + int key = -1; + + if (ipmi_bt_transaction_state != 0) { + // Deactivate interrupts on entering critical section + key = irq_lock(); + irqs_locked = 1; + } + #if (WITH_ZEPHYR) if (ipmi_bt_transaction_state != 0) { // Temporarily raise service thread priority @@ -1565,8 +1579,11 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) } #if (ENABLE_LPC_FW_CYCLE_DMA) - // Deactivate interrupts on entering critical section - int key = irq_lock(); + if (!irqs_locked) + { + // Deactivate interrupts on entering critical section + key = irq_lock(); + } // Disable DMA engine dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_DMA_CONFIG1); @@ -1631,8 +1648,11 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) } write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_DMA_CONFIG1, dword); - // Re-activate interupts on exiting critical section - irq_unlock(key); + if (!irqs_locked) + { + // Re-activate interupts on exiting critical section + irq_unlock(key); + } #endif // Generate response @@ -1786,7 +1806,7 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) // Send response // A full copy is done so as to ensure any potentially sensitive data stored // in the IPMI BT buffer from a previous request is overwritten - *response_ptr = response; + memcpy(response_ptr, &response, sizeof(ipmi_response_message_t)); // Signal BMC data ready dword = 0; @@ -1804,6 +1824,12 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) if (ENABLE_IPMI_DEBUG) { printk("[IPMI] Response complete, returning to idle\n"); } + + // (Re)enable IPMI BT IRQ + dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1); + dword |= ((1 & AQUILA_LPC_CTL_EN_IPMI_BT_IRQ_MASK) << AQUILA_LPC_CTL_EN_IPMI_BT_IRQ_SHIFT); + write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1, dword); + ipmi_bt_transaction_state = 0; } break; @@ -1812,6 +1838,13 @@ static int process_host_to_bmc_ipmi_bt_transactions(void) break; } + if (irqs_locked) + { + // Re-activate interupts on exiting critical section + irq_unlock(key); + irqs_locked = 0; + } + return 0; }