@@ -193,6 +193,7 @@ typedef struct cxl_device_state {
struct {
MemoryRegion mailbox;
uint16_t payload_size;
+ uint8_t mbox_msi_n;
union {
uint8_t mbox_reg_state[CXL_MAILBOX_REGISTERS_LENGTH];
uint16_t mbox_reg_state16[CXL_MAILBOX_REGISTERS_LENGTH / 2];
@@ -345,10 +345,18 @@ static void device_reg_init_common(CXLDeviceState *cxl_dstate)
static void mailbox_reg_init_common(CXLDeviceState *cxl_dstate)
{
- /* 2048 payload size, with no interrupt */
+ const uint8_t msi_n = 9;
+
+ /* 2048 payload size */
ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
PAYLOAD_SIZE, CXL_MAILBOX_PAYLOAD_SHIFT);
cxl_dstate->payload_size = CXL_MAILBOX_MAX_PAYLOAD_SIZE;
+ /* irq support */
+ ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
+ BG_INT_CAP, 1);
+ ARRAY_FIELD_DP32(cxl_dstate->mbox_reg_state32, CXL_DEV_MAILBOX_CAP,
+ MSI_N, msi_n);
+ cxl_dstate->mbox_msi_n = msi_n;
}
static void memdev_reg_init_common(CXLDeviceState *cxl_dstate) { }
@@ -8,6 +8,8 @@
*/
#include "qemu/osdep.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_events.h"
#include "hw/pci/pci.h"
@@ -1092,28 +1094,16 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,
static void bg_timercb(void *opaque)
{
CXLCCI *cci = opaque;
- CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate;
- uint64_t bg_status_reg = 0;
uint64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
uint64_t total_time = cci->bg.starttime + cci->bg.runtime;
assert(cci->bg.runtime > 0);
- bg_status_reg = FIELD_DP64(bg_status_reg, CXL_DEV_BG_CMD_STS,
- OP, cci->bg.opcode);
if (now >= total_time) { /* we are done */
- uint64_t status_reg;
uint16_t ret = CXL_MBOX_SUCCESS;
cci->bg.complete_pct = 100;
- /* Clear bg */
- status_reg = FIELD_DP64(0, CXL_DEV_MAILBOX_STS, BG_OP, 0);
- cxl_dstate->mbox_reg_state64[R_CXL_DEV_MAILBOX_STS] = status_reg;
-
- bg_status_reg = FIELD_DP64(bg_status_reg, CXL_DEV_BG_CMD_STS,
- RET_CODE, ret);
-
- /* TODO add ad-hoc cmd succesful completion handling */
+ cci->bg.ret_code = ret;
qemu_log("Background command %04xh finished: %s\n",
cci->bg.opcode,
@@ -1124,14 +1114,21 @@ static void bg_timercb(void *opaque)
timer_mod(cci->bg.timer, now + CXL_MBOX_BG_UPDATE_FREQ);
}
- bg_status_reg = FIELD_DP64(bg_status_reg, CXL_DEV_BG_CMD_STS,
- PERCENTAGE_COMP, cci->bg.complete_pct);
- cxl_dstate->mbox_reg_state64[R_CXL_DEV_BG_CMD_STS] = bg_status_reg;
-
if (cci->bg.complete_pct == 100) {
+ /* TODO: generalize to switch CCI */
+ CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
+ CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate;
+ PCIDevice *pdev = PCI_DEVICE(cci->d);
+
cci->bg.starttime = 0;
/* registers are updated, allow new bg-capable cmds */
cci->bg.runtime = 0;
+
+ if (msix_enabled(pdev)) {
+ msix_notify(pdev, cxl_dstate->mbox_msi_n);
+ } else if (msi_enabled(pdev)) {
+ msi_notify(pdev, cxl_dstate->mbox_msi_n);
+ }
}
}