[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2 15/18] hw/block/nvme: Support Zone Descriptor Extensions
From: |
Klaus Jensen |
Subject: |
Re: [PATCH v2 15/18] hw/block/nvme: Support Zone Descriptor Extensions |
Date: |
Wed, 1 Jul 2020 18:32:32 +0200 |
On Jun 18 06:34, Dmitry Fomichev wrote:
> Zone Descriptor Extension is a label that can be assigned to a zone.
> It can be set to an Empty zone and it stays assigned until the zone
> is reset.
>
> This commit adds a new optional property, "zone_descr_ext_size", to
> the driver. Its value must be a multiple of 64 bytes. If this value
> is non-zero, it becomes possible to assign extensions of that size
> to any Empty zones. The default value for this property is 0,
> therefore setting extensions is disabled by default.
>
> Signed-off-by: Hans Holmberg <hans.holmberg@wdc.com>
> Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
> ---
> hw/block/nvme.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++---
> hw/block/nvme.h | 8 ++++++
> 2 files changed, 80 insertions(+), 4 deletions(-)
>
> diff --git a/hw/block/nvme.c b/hw/block/nvme.c
> index b9135a6b1f..eb41081627 100644
> --- a/hw/block/nvme.c
> +++ b/hw/block/nvme.c
> @@ -1360,6 +1360,26 @@ static bool nvme_cond_offline_all(uint8_t state)
> return state == NVME_ZONE_STATE_READ_ONLY;
> }
>
> +static uint16_t nvme_set_zd_ext(NvmeCtrl *n, NvmeNamespace *ns,
> + NvmeZone *zone, uint8_t state)
> +{
> + uint16_t status;
> +
> + if (state == NVME_ZONE_STATE_EMPTY) {
> + nvme_auto_transition_zone(n, ns, false, true);
> + status = nvme_aor_check(n, ns, 1, 0);
> + if (status != NVME_SUCCESS) {
> + return status;
> + }
> + nvme_aor_inc_active(n, ns);
> + zone->d.za |= NVME_ZA_ZD_EXT_VALID;
> + nvme_assign_zone_state(n, ns, zone, NVME_ZONE_STATE_CLOSED);
> + return NVME_SUCCESS;
> + }
> +
> + return NVME_ZONE_INVAL_TRANSITION;
> +}
> +
> static uint16_t name_do_zone_op(NvmeCtrl *n, NvmeNamespace *ns,
> NvmeZone *zone, uint8_t state, bool all,
> uint16_t (*op_hndlr)(NvmeCtrl *, NvmeNamespace *, NvmeZone *,
> @@ -1388,13 +1408,16 @@ static uint16_t name_do_zone_op(NvmeCtrl *n,
> NvmeNamespace *ns,
> static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n, NvmeNamespace *ns,
> NvmeCmd *cmd, NvmeRequest *req)
> {
> + NvmeRwCmd *rw;
> uint32_t dw13 = le32_to_cpu(cmd->cdw13);
> + uint64_t prp1, prp2;
> uint64_t slba = 0;
> uint64_t zone_idx = 0;
> uint16_t status;
> uint8_t action, state;
> bool all;
> NvmeZone *zone;
> + uint8_t *zd_ext;
>
> action = dw13 & 0xff;
> all = dw13 & 0x100;
> @@ -1449,7 +1472,25 @@ static uint16_t nvme_zone_mgmt_send(NvmeCtrl *n,
> NvmeNamespace *ns,
>
> case NVME_ZONE_ACTION_SET_ZD_EXT:
> trace_pci_nvme_set_descriptor_extension(slba, zone_idx);
> - return NVME_INVALID_FIELD | NVME_DNR;
> + if (all || !n->params.zd_extension_size) {
> + return NVME_INVALID_FIELD | NVME_DNR;
> + }
> + zd_ext = nvme_get_zd_extension(n, ns, zone_idx);
> + rw = (NvmeRwCmd *)cmd;
> + prp1 = le64_to_cpu(rw->prp1);
> + prp2 = le64_to_cpu(rw->prp2);
> + status = nvme_dma_write_prp(n, zd_ext, n->params.zd_extension_size,
> + prp1, prp2);
> + if (status) {
> + trace_pci_nvme_err_zd_extension_map_error(zone_idx);
> + return status;
> + }
> +
> + status = nvme_set_zd_ext(n, ns, zone, state);
> + if (status == NVME_SUCCESS) {
> + trace_pci_nvme_zd_extension_set(zone_idx);
> + return status;
> + }
> break;
>
> default:
> @@ -1528,7 +1569,7 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n,
> NvmeNamespace *ns,
> return NVME_INVALID_FIELD | NVME_DNR;
> }
>
> - if (zra == NVME_ZONE_REPORT_EXTENDED) {
> + if (zra == NVME_ZONE_REPORT_EXTENDED && !n->params.zd_extension_size) {
> return NVME_INVALID_FIELD | NVME_DNR;
> }
>
> @@ -1540,6 +1581,9 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n,
> NvmeNamespace *ns,
> partial = (dw13 >> 16) & 0x01;
>
> zone_entry_sz = sizeof(NvmeZoneDescr);
> + if (zra == NVME_ZONE_REPORT_EXTENDED) {
> + zone_entry_sz += n->params.zd_extension_size;
> + }
>
> max_zones = (len - sizeof(NvmeZoneReportHeader)) / zone_entry_sz;
> buf = g_malloc0(len);
> @@ -1571,6 +1615,14 @@ static uint16_t nvme_zone_mgmt_recv(NvmeCtrl *n,
> NvmeNamespace *ns,
> z->wp = cpu_to_le64(~0ULL);
> }
>
> + if (zra == NVME_ZONE_REPORT_EXTENDED) {
> + if (zs->d.za & NVME_ZA_ZD_EXT_VALID) {
> + memcpy(buf_p, nvme_get_zd_extension(n, ns, zone_index),
> + n->params.zd_extension_size);
> + }
> + buf_p += n->params.zd_extension_size;
> + }
> +
> zone_index++;
> }
>
> @@ -2337,7 +2389,7 @@ static uint16_t nvme_handle_changed_zone_log(NvmeCtrl
> *n, NvmeCmd *cmd,
> continue;
> }
> num_aen_zones++;
> - if (zone->d.za) {
> + if (zone->d.za & ~NVME_ZA_ZD_EXT_VALID) {
> trace_pci_nvme_reporting_changed_zone(zone->d.zslba, zone->d.za);
> *zid_ptr++ = cpu_to_le64(zone->d.zslba);
> nids++;
> @@ -2936,6 +2988,7 @@ static int nvme_init_zone_meta(NvmeCtrl *n,
> NvmeNamespace *ns,
> ns->imp_open_zones = g_malloc0(sizeof(NvmeZoneList));
> ns->closed_zones = g_malloc0(sizeof(NvmeZoneList));
> ns->full_zones = g_malloc0(sizeof(NvmeZoneList));
> + ns->zd_extensions = g_malloc0(n->params.zd_extension_size *
> n->num_zones);
> zone = ns->zone_array;
>
> nvme_init_zone_list(ns->exp_open_zones);
> @@ -3010,6 +3063,17 @@ static void nvme_zoned_init_ctrl(NvmeCtrl *n, Error
> **errp)
> if (n->params.max_active_zones > nz) {
> n->params.max_active_zones = nz;
> }
> + if (n->params.zd_extension_size) {
> + if (n->params.zd_extension_size & 0x3f) {
> + error_setg(errp,
> + "zone descriptor extension size must be a multiple of 64B");
> + return;
> + }
> + if ((n->params.zd_extension_size >> 6) > 0xff) {
> + error_setg(errp, "zone descriptor extension size is too large");
> + return;
> + }
> + }
>
> if (n->params.zone_async_events) {
> n->ae_cfg |= NVME_AEN_CFG_ZONE_DESCR_CHNGD_NOTICES;
> @@ -3040,7 +3104,8 @@ static int nvme_zoned_init_ns(NvmeCtrl *n,
> NvmeNamespace *ns, int lba_index,
> ns->id_ns_zoned->ozcs = n->params.cross_zone_read ? 0x01 : 0x00;
>
> ns->id_ns_zoned->lbafe[lba_index].zsze =
> cpu_to_le64(n->params.zone_size);
> - ns->id_ns_zoned->lbafe[lba_index].zdes = 0;
> + ns->id_ns_zoned->lbafe[lba_index].zdes =
> + n->params.zd_extension_size >> 6; /* Units of 64B */
>
> if (n->params.fill_pattern == 0) {
> ns->id_ns.dlfeat = 0x01;
> @@ -3063,6 +3128,7 @@ static void nvme_zoned_clear(NvmeCtrl *n)
> g_free(ns->imp_open_zones);
> g_free(ns->closed_zones);
> g_free(ns->full_zones);
> + g_free(ns->zd_extensions);
> }
> }
>
> @@ -3396,6 +3462,8 @@ static Property nvme_props[] = {
> DEFINE_PROP_UINT64("zone_size", NvmeCtrl, params.zone_size, 512),
> DEFINE_PROP_UINT64("zone_capacity", NvmeCtrl, params.zone_capacity, 512),
> DEFINE_PROP_UINT32("zone_append_max_size", NvmeCtrl, params.zamds_bs, 0),
> + DEFINE_PROP_UINT32("zone_descr_ext_size", NvmeCtrl,
> + params.zd_extension_size, 0),
> DEFINE_PROP_INT32("max_active", NvmeCtrl, params.max_active_zones, 0),
> DEFINE_PROP_INT32("max_open", NvmeCtrl, params.max_open_zones, 0),
> DEFINE_PROP_UINT64("reset_rcmnd_delay", NvmeCtrl, params.rzr_delay_usec,
> 0),
> diff --git a/hw/block/nvme.h b/hw/block/nvme.h
> index e63f7736d7..4251295917 100644
> --- a/hw/block/nvme.h
> +++ b/hw/block/nvme.h
> @@ -24,6 +24,7 @@ typedef struct NvmeParams {
> uint64_t zone_capacity;
> int32_t max_active_zones;
> int32_t max_open_zones;
> + uint32_t zd_extension_size;
> uint64_t rzr_delay_usec;
> uint64_t rrl_usec;
> uint64_t fzr_delay_usec;
> @@ -123,6 +124,7 @@ typedef struct NvmeNamespace {
> NvmeZoneList *imp_open_zones;
> NvmeZoneList *closed_zones;
> NvmeZoneList *full_zones;
> + uint8_t *zd_extensions;
> int32_t nr_open_zones;
> int32_t nr_active_zones;
> bool aen_pending;
> @@ -221,6 +223,12 @@ static inline bool nvme_wp_is_valid(NvmeZone *zone)
> st != NVME_ZONE_STATE_OFFLINE;
> }
>
> +static inline uint8_t *nvme_get_zd_extension(NvmeCtrl *n,
> + NvmeNamespace *ns, uint32_t zone_idx)
> +{
> + return &ns->zd_extensions[zone_idx * n->params.zd_extension_size];
> +}
> +
> /*
> * Initialize a zone list head.
> */
> --
> 2.21.0
>
>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH v2 15/18] hw/block/nvme: Support Zone Descriptor Extensions,
Klaus Jensen <=