On Tue, 13 Aug 2024 15:12:55 -0700
Davidlohr Bueso <d...@stgolabs.net> wrote:

> As of 3.1 spec, background commands can be canceled with a new
> abort command. Implement the support, which is advertised in
> the CEL. No ad-hoc context undoing is necessary as all the
> command logic of the running bg command is done upon completion.
> Arbitrarily, the on-going background cmd will not be aborted if
> already at least 85% done;
> 
> A mutex is introduced to stabilize mbox request cancel command vs
> the timer callback being fired scenarios (as well as reading the
> mbox registers). While some operations under critical regions
> may be unnecessary (irq notifying, cmd callbacks), this is not
> a path where performance is important, so simplicity is preferred.
> 
> Tested-by: Ajay Joshi <ajay.open...@micron.com>
> Reviewed-by: Ajay Joshi <ajay.open...@micron.com>
> Signed-off-by: Davidlohr Bueso <d...@stgolabs.net>

+CC qemu-devel

No comments inline and LGTM. I'll queue it on my tree and push
that out on gitlab sometime soonish.

J
> ---
> 
> Changes based on the following thread:
> https://lore.kernel.org/linux-cxl/20240729102010.20996-1-ajay.open...@micron.com
> 
>  - Added a mutex (and expanded CCI to have a destroy counterpart).
>    An 'initialized' flag is added for correctly handling the reset()
>    case.
>  - Added the case where cancel is not done.
>  - Picked up Ajay's tags but it would be good to re-review/test if
>    possible.
> 
>  hw/cxl/cxl-device-utils.c    |  5 ++-
>  hw/cxl/cxl-mailbox-utils.c   | 63 +++++++++++++++++++++++++++++++++---
>  hw/mem/cxl_type3.c           |  8 ++++-
>  include/hw/cxl/cxl_device.h  |  4 +++
>  include/hw/cxl/cxl_mailbox.h |  1 +
>  5 files changed, 74 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c
> index 035d034f6dd8..1a9779ed8201 100644
> --- a/hw/cxl/cxl-device-utils.c
> +++ b/hw/cxl/cxl-device-utils.c
> @@ -95,11 +95,14 @@ static uint64_t mailbox_reg_read(void *opaque, hwaddr 
> offset, unsigned size)
>          }
>          if (offset == A_CXL_DEV_MAILBOX_STS) {
>              uint64_t status_reg = cxl_dstate->mbox_reg_state64[offset / 
> size];
> -            if (cci->bg.complete_pct) {
> +
> +            qemu_mutex_lock(&cci->bg.lock);
> +            if (cci->bg.complete_pct == 100 || cci->bg.aborted) {
>                  status_reg = FIELD_DP64(status_reg, CXL_DEV_MAILBOX_STS, 
> BG_OP,
>                                          0);
>                  cxl_dstate->mbox_reg_state64[offset / size] = status_reg;
>              }
> +            qemu_mutex_unlock(&cci->bg.lock);
>          }
>          return cxl_dstate->mbox_reg_state64[offset / size];
>      default:
> diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
> index b752920ec88a..ff12dfc3dcc4 100644
> --- a/hw/cxl/cxl-mailbox-utils.c
> +++ b/hw/cxl/cxl-mailbox-utils.c
> @@ -56,6 +56,7 @@ enum {
>      INFOSTAT    = 0x00,
>          #define IS_IDENTIFY   0x1
>          #define BACKGROUND_OPERATION_STATUS    0x2
> +        #define BACKGROUND_OPERATION_ABORT     0x5
>      EVENTS      = 0x01,
>          #define GET_RECORDS   0x0
>          #define CLEAR_RECORDS   0x1
> @@ -624,6 +625,38 @@ static CXLRetCode cmd_infostat_bg_op_sts(const struct 
> cxl_cmd *cmd,
>      return CXL_MBOX_SUCCESS;
>  }
>  
> +/* CXL r3.1 Section 8.2.9.1.5: Request Abort Background Operation (Opcode 
> 0005h) */
> +static CXLRetCode cmd_infostat_bg_op_abort(const struct cxl_cmd *cmd,
> +                                           uint8_t *payload_in,
> +                                           size_t len_in,
> +                                           uint8_t *payload_out,
> +                                           size_t *len_out,
> +                                           CXLCCI *cci)
> +{
> +    int bg_set = cci->bg.opcode >> 8;
> +    int bg_cmd = cci->bg.opcode & 0xff;
> +    const struct cxl_cmd *bg_c = &cci->cxl_cmd_set[bg_set][bg_cmd];
> +
> +    if (!(bg_c->effect & CXL_MBOX_BACKGROUND_OPERATION_ABORT)) {
> +        return CXL_MBOX_REQUEST_ABORT_NOTSUP;
> +    }
> +
> +    qemu_mutex_lock(&cci->bg.lock);
> +    if (cci->bg.runtime) {
> +        /* operation is near complete, let it finish */
> +        if (cci->bg.complete_pct < 85) {
> +            timer_del(cci->bg.timer);
> +            cci->bg.ret_code = CXL_MBOX_ABORTED;
> +            cci->bg.starttime = 0;
> +            cci->bg.runtime = 0;
> +            cci->bg.aborted = true;
> +        }
> +    }
> +    qemu_mutex_unlock(&cci->bg.lock);
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +
>  #define CXL_FW_SLOTS 2
>  #define CXL_FW_SIZE  0x02000000 /* 32 mb */
>  
> @@ -2665,6 +2698,8 @@ static CXLRetCode cmd_dcd_release_dyn_cap(const struct 
> cxl_cmd *cmd,
>  }
>  
>  static const struct cxl_cmd cxl_cmd_set[256][256] = {
> +    [INFOSTAT][BACKGROUND_OPERATION_ABORT] = { "BACKGROUND_OPERATION_ABORT",
> +        cmd_infostat_bg_op_abort, 0, 0 },
>      [EVENTS][GET_RECORDS] = { "EVENTS_GET_RECORDS",
>          cmd_events_get_records, 1, 0 },
>      [EVENTS][CLEAR_RECORDS] = { "EVENTS_CLEAR_RECORDS",
> @@ -2708,7 +2743,8 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
>      [SANITIZE][OVERWRITE] = { "SANITIZE_OVERWRITE", cmd_sanitize_overwrite, 
> 0,
>          (CXL_MBOX_IMMEDIATE_DATA_CHANGE |
>           CXL_MBOX_SECURITY_STATE_CHANGE |
> -         CXL_MBOX_BACKGROUND_OPERATION)},
> +         CXL_MBOX_BACKGROUND_OPERATION |
> +         CXL_MBOX_BACKGROUND_OPERATION_ABORT)},
>      [PERSISTENT_MEM][GET_SECURITY_STATE] = { "GET_SECURITY_STATE",
>          cmd_get_security_state, 0, 0 },
>      [MEDIA_AND_POISON][GET_POISON_LIST] = { 
> "MEDIA_AND_POISON_GET_POISON_LIST",
> @@ -2721,7 +2757,8 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = {
>          "MEDIA_AND_POISON_GET_SCAN_MEDIA_CAPABILITIES",
>          cmd_media_get_scan_media_capabilities, 16, 0 },
>      [MEDIA_AND_POISON][SCAN_MEDIA] = { "MEDIA_AND_POISON_SCAN_MEDIA",
> -        cmd_media_scan_media, 17, CXL_MBOX_BACKGROUND_OPERATION },
> +        cmd_media_scan_media, 17,
> +        (CXL_MBOX_BACKGROUND_OPERATION | 
> CXL_MBOX_BACKGROUND_OPERATION_ABORT)},
>      [MEDIA_AND_POISON][GET_SCAN_MEDIA_RESULTS] = {
>          "MEDIA_AND_POISON_GET_SCAN_MEDIA_RESULTS",
>          cmd_media_get_scan_media_results, 0, 0 },
> @@ -2745,6 +2782,8 @@ static const struct cxl_cmd cxl_cmd_set_sw[256][256] = {
>      [INFOSTAT][IS_IDENTIFY] = { "IDENTIFY", cmd_infostat_identify, 0, 0 },
>      [INFOSTAT][BACKGROUND_OPERATION_STATUS] = { 
> "BACKGROUND_OPERATION_STATUS",
>          cmd_infostat_bg_op_sts, 0, 0 },
> +    [INFOSTAT][BACKGROUND_OPERATION_ABORT] = { "BACKGROUND_OPERATION_ABORT",
> +        cmd_infostat_bg_op_abort, 0, 0 },
>      [TIMESTAMP][GET] = { "TIMESTAMP_GET", cmd_timestamp_get, 0, 0 },
>      [TIMESTAMP][SET] = { "TIMESTAMP_SET", cmd_timestamp_set, 8,
>                           CXL_MBOX_IMMEDIATE_POLICY_CHANGE },
> @@ -2831,6 +2870,7 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, 
> uint8_t cmd,
>          cci->bg.opcode = (set << 8) | cmd;
>  
>          cci->bg.complete_pct = 0;
> +        cci->bg.aborted = false;
>          cci->bg.ret_code = 0;
>  
>          now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
> @@ -2844,10 +2884,12 @@ int cxl_process_cci_message(CXLCCI *cci, uint8_t set, 
> uint8_t cmd,
>  static void bg_timercb(void *opaque)
>  {
>      CXLCCI *cci = opaque;
> -    uint64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
> -    uint64_t total_time = cci->bg.starttime + cci->bg.runtime;
> +    uint64_t now, total_time;
> +
> +    qemu_mutex_lock(&cci->bg.lock);
>  
> -    assert(cci->bg.runtime > 0);
> +    now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
> +    total_time = cci->bg.starttime + cci->bg.runtime;
>  
>      if (now >= total_time) { /* we are done */
>          uint16_t ret = CXL_MBOX_SUCCESS;
> @@ -2899,6 +2941,8 @@ static void bg_timercb(void *opaque)
>              msi_notify(pdev, cxl_dstate->mbox_msi_n);
>          }
>      }
> +
> +    qemu_mutex_unlock(&cci->bg.lock);
>  }
>  
>  static void cxl_rebuild_cel(CXLCCI *cci)
> @@ -2927,12 +2971,21 @@ void cxl_init_cci(CXLCCI *cci, size_t payload_max)
>      cci->bg.complete_pct = 0;
>      cci->bg.starttime = 0;
>      cci->bg.runtime = 0;
> +    cci->bg.aborted = false;
>      cci->bg.timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
>                                   bg_timercb, cci);
> +    qemu_mutex_init(&cci->bg.lock);
>  
>      memset(&cci->fw, 0, sizeof(cci->fw));
>      cci->fw.active_slot = 1;
>      cci->fw.slot[cci->fw.active_slot - 1] = true;
> +    cci->initialized = true;
> +}
> +
> +void cxl_destroy_cci(CXLCCI *cci)
> +{
> +    qemu_mutex_destroy(&cci->bg.lock);
> +    cci->initialized = false;
>  }
>  
>  static void cxl_copy_cci_commands(CXLCCI *cci, const struct cxl_cmd 
> (*cxl_cmds)[256])
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index 4114163324bd..f04aa58ea85d 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -961,6 +961,7 @@ static void ct3_exit(PCIDevice *pci_dev)
>      pcie_aer_exit(pci_dev);
>      cxl_doe_cdat_release(cxl_cstate);
>      g_free(regs->special_ops);
> +    cxl_destroy_cci(&ct3d->cci);
>      if (ct3d->dc.host_dc) {
>          cxl_destroy_dc_regions(ct3d);
>          address_space_destroy(&ct3d->dc.host_dc_as);
> @@ -1209,12 +1210,17 @@ static void ct3d_reset(DeviceState *dev)
>       * Bring up an endpoint to target with MCTP over VDM.
>       * This device is emulating an MLD with single LD for now.
>       */
> +    if (ct3d->vdm_fm_owned_ld_mctp_cci.initialized) {
> +        cxl_destroy_cci(&ct3d->vdm_fm_owned_ld_mctp_cci);
> +    }
>      cxl_initialize_t3_fm_owned_ld_mctpcci(&ct3d->vdm_fm_owned_ld_mctp_cci,
>                                            DEVICE(ct3d), DEVICE(ct3d),
>                                            512); /* Max payload made up */
> +    if (ct3d->ld0_cci.initialized) {
> +        cxl_destroy_cci(&ct3d->ld0_cci);
> +    }
>      cxl_initialize_t3_ld_cci(&ct3d->ld0_cci, DEVICE(ct3d), DEVICE(ct3d),
>                               512); /* Max payload made up */
> -
>  }
>  
>  static Property ct3_props[] = {
> diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
> index e14e56ae4bc2..c0e8d40053db 100644
> --- a/include/hw/cxl/cxl_device.h
> +++ b/include/hw/cxl/cxl_device.h
> @@ -176,10 +176,12 @@ typedef struct CXLCCI {
>          uint16_t opcode;
>          uint16_t complete_pct;
>          uint16_t ret_code; /* Current value of retcode */
> +        bool aborted;
>          uint64_t starttime;
>          /* set by each bg cmd, cleared by the bg_timer when complete */
>          uint64_t runtime;
>          QEMUTimer *timer;
> +        QemuMutex lock; /* serializes mbox abort vs timer cb */
>      } bg;
>  
>      /* firmware update */
> @@ -201,6 +203,7 @@ typedef struct CXLCCI {
>      DeviceState *d;
>      /* Pointer to the device hosting the protocol conversion */
>      DeviceState *intf;
> +    bool initialized;
>  } CXLCCI;
>  
>  typedef struct cxl_device_state {
> @@ -316,6 +319,7 @@ void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState 
> *d, size_t payload_max);
>  void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
>                                    DeviceState *d, size_t payload_max);
>  void cxl_init_cci(CXLCCI *cci, size_t payload_max);
> +void cxl_destroy_cci(CXLCCI *cci);
>  void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd 
> (*cxl_cmd_set)[256],
>                            size_t payload_max);
>  int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,
> diff --git a/include/hw/cxl/cxl_mailbox.h b/include/hw/cxl/cxl_mailbox.h
> index beb048052e1b..9008402d1c46 100644
> --- a/include/hw/cxl/cxl_mailbox.h
> +++ b/include/hw/cxl/cxl_mailbox.h
> @@ -14,5 +14,6 @@
>  #define CXL_MBOX_IMMEDIATE_LOG_CHANGE (1 << 4)
>  #define CXL_MBOX_SECURITY_STATE_CHANGE (1 << 5)
>  #define CXL_MBOX_BACKGROUND_OPERATION (1 << 6)
> +#define CXL_MBOX_BACKGROUND_OPERATION_ABORT (1 << 7)
>  
>  #endif


Reply via email to