All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
To: <nifan.cxl@gmail.com>
Cc: <qemu-devel@nongnu.org>, <linux-cxl@vger.kernel.org>,
	<gregory.price@memverge.com>, <ira.weiny@intel.com>,
	<dan.j.williams@intel.com>, <a.manzanares@samsung.com>,
	<dave@stgolabs.net>, <nmtadam.samsung@gmail.com>,
	<jim.harris@samsung.com>, <Jorgen.Hansen@wdc.com>,
	<wj28.lee@gmail.com>, Fan Ni <fan.ni@samsung.com>
Subject: Re: [PATCH v5 08/13] hw/cxl/cxl-mailbox-utils: Add mailbox commands to support add/release dynamic capacity response
Date: Wed, 6 Mar 2024 17:28:27 +0000	[thread overview]
Message-ID: <20240306172827.000052dc@Huawei.com> (raw)
In-Reply-To: <20240304194331.1586191-9-nifan.cxl@gmail.com>

On Mon,  4 Mar 2024 11:34:03 -0800
nifan.cxl@gmail.com wrote:

> From: Fan Ni <fan.ni@samsung.com>
> 
> Per CXL spec 3.1, two mailbox commands are implemented:
> Add Dynamic Capacity Response (Opcode 4802h) 8.2.9.9.9.3, and
> Release Dynamic Capacity (Opcode 4803h) 8.2.9.9.9.4.
> 
> Signed-off-by: Fan Ni <fan.ni@samsung.com>

Hmm. So I had a thought which would work for what you
have here. See include/qemu/range.h
I like the region merging stuff that is also in the list operators
but we shouldn't use that because we have other reasons not to
fuse ranges (sequence numbering etc)

We could make an extent a wrapper around a struct Range though
so that we can use the comparison stuff directly.
+ we can use the list manipulation in there as the basis for a future
extent merging infrastructure that is tag and sequence number (if
provided - so shared capacity or pmem) aware.

Jonathan


> ---
> +
> +/*
> + * CXL r3.1 Table 8-168: Add Dynamic Capacity Response Input Payload
> + * CXL r3.1 Table 8-170: Release Dynamic Capacity Input Payload
> + */
> +typedef struct CXLUpdateDCExtentListInPl {
> +    uint32_t num_entries_updated;
> +    uint8_t flags;
> +    uint8_t rsvd[3];
> +    /* CXL r3.1 Table 8-169: Updated Extent */
> +    struct {
> +        uint64_t start_dpa;
> +        uint64_t len;
> +        uint8_t rsvd[8];
> +    } QEMU_PACKED updated_entries[];
> +} QEMU_PACKED CXLUpdateDCExtentListInPl;
> +
> +/*
> + * For the extents in the extent list to operate, check whether they are valid
> + * 1. The extent should be in the range of a valid DC region;
> + * 2. The extent should not cross multiple regions;
> + * 3. The start DPA and the length of the extent should align with the block
> + * size of the region;
> + * 4. The address range of multiple extents in the list should not overlap.

Hmm. Interesting.  I was thinking a given add / remove command rather than
just the extents can't overlap a region.  However I can't find text on that
so I believe your interpretation is correct. It is only specified for the
event records, but that is good enough I think.  We might want to propose
tightening the spec on this to allow devices to say no to such complex
extent lists. Maybe a nice friendly Memory vendor should query this one if
it's a potential problem for real devices.  Might not be!

> + */
> +static CXLRetCode cxl_detect_malformed_extent_list(CXLType3Dev *ct3d,
> +        const CXLUpdateDCExtentListInPl *in)
> +{
> +    uint64_t min_block_size = UINT64_MAX;
> +    CXLDCRegion *region = &ct3d->dc.regions[0];
> +    CXLDCRegion *lastregion = &ct3d->dc.regions[ct3d->dc.num_regions - 1];
> +    g_autofree unsigned long *blk_bitmap = NULL;
> +    uint64_t dpa, len;
> +    uint32_t i;
> +
> +    for (i = 0; i < ct3d->dc.num_regions; i++) {
> +        region = &ct3d->dc.regions[i];
> +        min_block_size = MIN(min_block_size, region->block_size);
> +    }
> +
> +    blk_bitmap = bitmap_new((lastregion->base + lastregion->len -
> +                             ct3d->dc.regions[0].base) / min_block_size);
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        region = cxl_find_dc_region(ct3d, dpa, len);
> +        if (!region) {
> +            return CXL_MBOX_INVALID_PA;
> +        }
> +
> +        dpa -= ct3d->dc.regions[0].base;
> +        if (dpa % region->block_size || len % region->block_size) {
> +            return CXL_MBOX_INVALID_EXTENT_LIST;
> +        }
> +        /* the dpa range already covered by some other extents in the list */
> +        if (test_any_bits_set(blk_bitmap, dpa / min_block_size,
> +            len / min_block_size)) {
> +            return CXL_MBOX_INVALID_EXTENT_LIST;
> +        }
> +        bitmap_set(blk_bitmap, dpa / min_block_size, len / min_block_size);
> +   }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +
> +/*
> + * CXL r3.1 section 8.2.9.9.9.3: Add Dynamic Capacity Response (Opcode 4802h)
> + * An extent is added to the extent list and becomes usable only after the
> + * response is processed successfully
> + */
> +static CXLRetCode cmd_dcd_add_dyn_cap_rsp(const struct cxl_cmd *cmd,
> +                                          uint8_t *payload_in,
> +                                          size_t len_in,
> +                                          uint8_t *payload_out,
> +                                          size_t *len_out,
> +                                          CXLCCI *cci)
> +{
> +    CXLUpdateDCExtentListInPl *in = (void *)payload_in;
> +    CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> +    CXLDCExtentList *extent_list = &ct3d->dc.extents;
> +    CXLDCExtent *ent;
> +    uint32_t i;
> +    uint64_t dpa, len;
> +    CXLRetCode ret;
> +
> +    if (in->num_entries_updated == 0) {
> +        return CXL_MBOX_SUCCESS;
> +    }
> +
> +    /* Adding extents causes exceeding device's extent tracking ability. */
> +    if (in->num_entries_updated + ct3d->dc.total_extent_count >
> +        CXL_NUM_EXTENTS_SUPPORTED) {
> +        return CXL_MBOX_RESOURCES_EXHAUSTED;
> +    }
> +
> +    ret = cxl_detect_malformed_extent_list(ct3d, in);
> +    if (ret != CXL_MBOX_SUCCESS) {
> +        return ret;
> +    }
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        /*
> +         * Check if the DPA range of the to-be-added extent overlaps with
> +         * existing extent list maintained by the device.
> +         */
> +        QTAILQ_FOREACH(ent, extent_list, node) {

There are too many checks in here for an overlapping test.

Conditions are

	|  Extent tested against |
|  Overlap entirely                 |
| overlap left edge |
                    | overlap right edge |
Think of it in the inverse condition and it is easier to reason about.

              | Extent tested against |
| to left |---                        ---| to right |

which I think is something like.

        if (!((dpa + len <= ent->start_dpa) || (dpa >= ent->start_dpa + ent->len)) {
		 return CXL_MBOX_INVALID_PA;
	}

Hmm. For internal tracking (not the exposed values) we should probably use
struct range from include/qemu/range.h.
Felt like there had to be something better than doing this ourselves so I went
looking.  Note it uses inclusive upper bound so be careful with that!

Advantage is we get this checks for free.
https://elixir.bootlin.com/qemu/latest/source/include/qemu/range.h#L152
range_overlaps_range()

There are functions to set them up nicely for us and by base and size
as well which should tidy that part up.

	    

> +            if (ent->start_dpa <= dpa &&
> +                    dpa + len <= ent->start_dpa + ent->len) {
> +                return CXL_MBOX_INVALID_PA;
> +            /* Overlapping one end of the other */
> +            } else if ((dpa < ent->start_dpa + ent->len &&
> +                        dpa + len > ent->start_dpa + ent->len) ||
> +                       (dpa < ent->start_dpa && dpa + len > ent->start_dpa)) {
> +                return CXL_MBOX_INVALID_PA;
> +            }
> +        }
> +
> +        /*
> +         * TODO: we will add a pending extent list based on event log record
> +         * and verify the input response; also, the "More" flag is not
> +         * considered at the moment.
> +         */
> +
> +        cxl_insert_extent_to_extent_list(extent_list, dpa, len, NULL, 0);
> +        ct3d->dc.total_extent_count += 1;
> +    }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +
> +/*
> + * CXL r3.1 section 8.2.9.9.9.4: Release Dynamic Capacity (Opcode 4803h)
> + */
> +static CXLRetCode cmd_dcd_release_dyn_cap(const struct cxl_cmd *cmd,
> +                                          uint8_t *payload_in,
> +                                          size_t len_in,
> +                                          uint8_t *payload_out,
> +                                          size_t *len_out,
> +                                          CXLCCI *cci)
> +{
> +    CXLUpdateDCExtentListInPl *in = (void *)payload_in;
> +    CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> +    CXLDCExtentList *extent_list = &ct3d->dc.extents;
> +    CXLDCExtent *ent;
> +    uint32_t i;
> +    uint64_t dpa, len;
> +    CXLRetCode ret;
> +
> +    if (in->num_entries_updated == 0) {
> +        return CXL_MBOX_INVALID_INPUT;
> +    }
> +
> +    ret = cxl_detect_malformed_extent_list(ct3d, in);
> +    if (ret != CXL_MBOX_SUCCESS) {
> +        return ret;
> +    }
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        bool found = false;
> +
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        QTAILQ_FOREACH(ent, extent_list, node) {
> +            /* Found the extent overlapping with */
> +            if (ent->start_dpa <= dpa && dpa < ent->start_dpa + ent->len) {
> +                if (dpa + len <= ent->start_dpa + ent->len) {
> +                    /*
> +                     * The incoming extent covers a portion of an extent
> +                     * in the device extent list, remove only the overlapping
> +                     * portion, meaning
> +                     * 1. the portions that are not covered by the incoming
> +                     *    extent at both end of the original extent will become
> +                     *    new extents and inserted to the extent list; and
> +                     * 2. the original extent is removed from the extent list;
> +                     * 3. DC extent count is updated accordingly.
> +                     */
> +                    uint64_t ent_start_dpa = ent->start_dpa;
> +                    uint64_t ent_len = ent->len;
> +                    uint64_t len1 = dpa - ent_start_dpa;
> +                    uint64_t len2 = ent_start_dpa + ent_len - dpa - len;
> +
> +                    /*
> +                     * TODO: checking for possible extent overflow, will be
> +                     * moved into a dedicated function of detecting extent
> +                     * overflow.
> +                     */
> +                    if (len1 && len2 && ct3d->dc.total_extent_count ==
> +                        CXL_NUM_EXTENTS_SUPPORTED) {
> +                        return CXL_MBOX_RESOURCES_EXHAUSTED;
> +                    }
> +
> +                    found = true;
> +                    cxl_remove_extent_from_extent_list(extent_list, ent);
> +                    ct3d->dc.total_extent_count -= 1;
> +
> +                    if (len1) {
> +                        cxl_insert_extent_to_extent_list(extent_list,
> +                                                         ent_start_dpa, len1,
> +                                                         NULL, 0);
> +                        ct3d->dc.total_extent_count += 1;
> +                    }
> +                    if (len2) {
> +                        cxl_insert_extent_to_extent_list(extent_list, dpa + len,
> +                                                         len2, NULL, 0);
> +                        ct3d->dc.total_extent_count += 1;
> +                    }
> +                    break;
Maybe this makes sense after the support below is added, but at this
point in the series 
			return CXL_MBOX_SUCCESS;
then found isn't relevant so can drop that. Looks like you drop it later in the
series anyway.

> +                } else {
> +                    /*
> +                     * TODO: we reject the attempt to remove an extent that
> +                     * overlaps with multiple extents in the device for now,
> +                     * once the bitmap indicating whether a DPA range is
> +                     * covered by valid extents is introduced, will allow it.
> +                     */
> +                    return CXL_MBOX_INVALID_PA;
> +                }
> +            }
> +        }
> +
> +        if (!found) {
> +            /* Try to remove a non-existing extent. */
> +            return CXL_MBOX_INVALID_PA;
> +        }
> +    }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +

>  static const struct cxl_cmd cxl_cmd_set_sw[256][256] = {
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index 102fa8151e..dccfaaad3a 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -678,6 +678,16 @@ static bool cxl_create_dc_regions(CXLType3Dev *ct3d, Error **errp)
>      return true;
>  }
>  
> +static void cxl_destroy_dc_regions(CXLType3Dev *ct3d)
> +{
> +    CXLDCExtent *ent;
> +
> +    while (!QTAILQ_EMPTY(&ct3d->dc.extents)) {
> +        ent = QTAILQ_FIRST(&ct3d->dc.extents);
> +        cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent);

Isn't this same a something like.
    QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node)) {
	cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent);
        //This wrapper is small enough I'd be tempted to just have the
        //code inline at the places it's called.

    }
> +    }
> +}


WARNING: multiple messages have this Message-ID (diff)
From: Jonathan Cameron via <qemu-devel@nongnu.org>
To: <nifan.cxl@gmail.com>
Cc: <qemu-devel@nongnu.org>, <linux-cxl@vger.kernel.org>,
	<gregory.price@memverge.com>, <ira.weiny@intel.com>,
	<dan.j.williams@intel.com>, <a.manzanares@samsung.com>,
	<dave@stgolabs.net>, <nmtadam.samsung@gmail.com>,
	<jim.harris@samsung.com>, <Jorgen.Hansen@wdc.com>,
	<wj28.lee@gmail.com>, Fan Ni <fan.ni@samsung.com>
Subject: Re: [PATCH v5 08/13] hw/cxl/cxl-mailbox-utils: Add mailbox commands to support add/release dynamic capacity response
Date: Wed, 6 Mar 2024 17:28:27 +0000	[thread overview]
Message-ID: <20240306172827.000052dc@Huawei.com> (raw)
In-Reply-To: <20240304194331.1586191-9-nifan.cxl@gmail.com>

On Mon,  4 Mar 2024 11:34:03 -0800
nifan.cxl@gmail.com wrote:

> From: Fan Ni <fan.ni@samsung.com>
> 
> Per CXL spec 3.1, two mailbox commands are implemented:
> Add Dynamic Capacity Response (Opcode 4802h) 8.2.9.9.9.3, and
> Release Dynamic Capacity (Opcode 4803h) 8.2.9.9.9.4.
> 
> Signed-off-by: Fan Ni <fan.ni@samsung.com>

Hmm. So I had a thought which would work for what you
have here. See include/qemu/range.h
I like the region merging stuff that is also in the list operators
but we shouldn't use that because we have other reasons not to
fuse ranges (sequence numbering etc)

We could make an extent a wrapper around a struct Range though
so that we can use the comparison stuff directly.
+ we can use the list manipulation in there as the basis for a future
extent merging infrastructure that is tag and sequence number (if
provided - so shared capacity or pmem) aware.

Jonathan


> ---
> +
> +/*
> + * CXL r3.1 Table 8-168: Add Dynamic Capacity Response Input Payload
> + * CXL r3.1 Table 8-170: Release Dynamic Capacity Input Payload
> + */
> +typedef struct CXLUpdateDCExtentListInPl {
> +    uint32_t num_entries_updated;
> +    uint8_t flags;
> +    uint8_t rsvd[3];
> +    /* CXL r3.1 Table 8-169: Updated Extent */
> +    struct {
> +        uint64_t start_dpa;
> +        uint64_t len;
> +        uint8_t rsvd[8];
> +    } QEMU_PACKED updated_entries[];
> +} QEMU_PACKED CXLUpdateDCExtentListInPl;
> +
> +/*
> + * For the extents in the extent list to operate, check whether they are valid
> + * 1. The extent should be in the range of a valid DC region;
> + * 2. The extent should not cross multiple regions;
> + * 3. The start DPA and the length of the extent should align with the block
> + * size of the region;
> + * 4. The address range of multiple extents in the list should not overlap.

Hmm. Interesting.  I was thinking a given add / remove command rather than
just the extents can't overlap a region.  However I can't find text on that
so I believe your interpretation is correct. It is only specified for the
event records, but that is good enough I think.  We might want to propose
tightening the spec on this to allow devices to say no to such complex
extent lists. Maybe a nice friendly Memory vendor should query this one if
it's a potential problem for real devices.  Might not be!

> + */
> +static CXLRetCode cxl_detect_malformed_extent_list(CXLType3Dev *ct3d,
> +        const CXLUpdateDCExtentListInPl *in)
> +{
> +    uint64_t min_block_size = UINT64_MAX;
> +    CXLDCRegion *region = &ct3d->dc.regions[0];
> +    CXLDCRegion *lastregion = &ct3d->dc.regions[ct3d->dc.num_regions - 1];
> +    g_autofree unsigned long *blk_bitmap = NULL;
> +    uint64_t dpa, len;
> +    uint32_t i;
> +
> +    for (i = 0; i < ct3d->dc.num_regions; i++) {
> +        region = &ct3d->dc.regions[i];
> +        min_block_size = MIN(min_block_size, region->block_size);
> +    }
> +
> +    blk_bitmap = bitmap_new((lastregion->base + lastregion->len -
> +                             ct3d->dc.regions[0].base) / min_block_size);
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        region = cxl_find_dc_region(ct3d, dpa, len);
> +        if (!region) {
> +            return CXL_MBOX_INVALID_PA;
> +        }
> +
> +        dpa -= ct3d->dc.regions[0].base;
> +        if (dpa % region->block_size || len % region->block_size) {
> +            return CXL_MBOX_INVALID_EXTENT_LIST;
> +        }
> +        /* the dpa range already covered by some other extents in the list */
> +        if (test_any_bits_set(blk_bitmap, dpa / min_block_size,
> +            len / min_block_size)) {
> +            return CXL_MBOX_INVALID_EXTENT_LIST;
> +        }
> +        bitmap_set(blk_bitmap, dpa / min_block_size, len / min_block_size);
> +   }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +
> +/*
> + * CXL r3.1 section 8.2.9.9.9.3: Add Dynamic Capacity Response (Opcode 4802h)
> + * An extent is added to the extent list and becomes usable only after the
> + * response is processed successfully
> + */
> +static CXLRetCode cmd_dcd_add_dyn_cap_rsp(const struct cxl_cmd *cmd,
> +                                          uint8_t *payload_in,
> +                                          size_t len_in,
> +                                          uint8_t *payload_out,
> +                                          size_t *len_out,
> +                                          CXLCCI *cci)
> +{
> +    CXLUpdateDCExtentListInPl *in = (void *)payload_in;
> +    CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> +    CXLDCExtentList *extent_list = &ct3d->dc.extents;
> +    CXLDCExtent *ent;
> +    uint32_t i;
> +    uint64_t dpa, len;
> +    CXLRetCode ret;
> +
> +    if (in->num_entries_updated == 0) {
> +        return CXL_MBOX_SUCCESS;
> +    }
> +
> +    /* Adding extents causes exceeding device's extent tracking ability. */
> +    if (in->num_entries_updated + ct3d->dc.total_extent_count >
> +        CXL_NUM_EXTENTS_SUPPORTED) {
> +        return CXL_MBOX_RESOURCES_EXHAUSTED;
> +    }
> +
> +    ret = cxl_detect_malformed_extent_list(ct3d, in);
> +    if (ret != CXL_MBOX_SUCCESS) {
> +        return ret;
> +    }
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        /*
> +         * Check if the DPA range of the to-be-added extent overlaps with
> +         * existing extent list maintained by the device.
> +         */
> +        QTAILQ_FOREACH(ent, extent_list, node) {

There are too many checks in here for an overlapping test.

Conditions are

	|  Extent tested against |
|  Overlap entirely                 |
| overlap left edge |
                    | overlap right edge |
Think of it in the inverse condition and it is easier to reason about.

              | Extent tested against |
| to left |---                        ---| to right |

which I think is something like.

        if (!((dpa + len <= ent->start_dpa) || (dpa >= ent->start_dpa + ent->len)) {
		 return CXL_MBOX_INVALID_PA;
	}

Hmm. For internal tracking (not the exposed values) we should probably use
struct range from include/qemu/range.h.
Felt like there had to be something better than doing this ourselves so I went
looking.  Note it uses inclusive upper bound so be careful with that!

Advantage is we get this checks for free.
https://elixir.bootlin.com/qemu/latest/source/include/qemu/range.h#L152
range_overlaps_range()

There are functions to set them up nicely for us and by base and size
as well which should tidy that part up.

	    

> +            if (ent->start_dpa <= dpa &&
> +                    dpa + len <= ent->start_dpa + ent->len) {
> +                return CXL_MBOX_INVALID_PA;
> +            /* Overlapping one end of the other */
> +            } else if ((dpa < ent->start_dpa + ent->len &&
> +                        dpa + len > ent->start_dpa + ent->len) ||
> +                       (dpa < ent->start_dpa && dpa + len > ent->start_dpa)) {
> +                return CXL_MBOX_INVALID_PA;
> +            }
> +        }
> +
> +        /*
> +         * TODO: we will add a pending extent list based on event log record
> +         * and verify the input response; also, the "More" flag is not
> +         * considered at the moment.
> +         */
> +
> +        cxl_insert_extent_to_extent_list(extent_list, dpa, len, NULL, 0);
> +        ct3d->dc.total_extent_count += 1;
> +    }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +
> +/*
> + * CXL r3.1 section 8.2.9.9.9.4: Release Dynamic Capacity (Opcode 4803h)
> + */
> +static CXLRetCode cmd_dcd_release_dyn_cap(const struct cxl_cmd *cmd,
> +                                          uint8_t *payload_in,
> +                                          size_t len_in,
> +                                          uint8_t *payload_out,
> +                                          size_t *len_out,
> +                                          CXLCCI *cci)
> +{
> +    CXLUpdateDCExtentListInPl *in = (void *)payload_in;
> +    CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
> +    CXLDCExtentList *extent_list = &ct3d->dc.extents;
> +    CXLDCExtent *ent;
> +    uint32_t i;
> +    uint64_t dpa, len;
> +    CXLRetCode ret;
> +
> +    if (in->num_entries_updated == 0) {
> +        return CXL_MBOX_INVALID_INPUT;
> +    }
> +
> +    ret = cxl_detect_malformed_extent_list(ct3d, in);
> +    if (ret != CXL_MBOX_SUCCESS) {
> +        return ret;
> +    }
> +
> +    for (i = 0; i < in->num_entries_updated; i++) {
> +        bool found = false;
> +
> +        dpa = in->updated_entries[i].start_dpa;
> +        len = in->updated_entries[i].len;
> +
> +        QTAILQ_FOREACH(ent, extent_list, node) {
> +            /* Found the extent overlapping with */
> +            if (ent->start_dpa <= dpa && dpa < ent->start_dpa + ent->len) {
> +                if (dpa + len <= ent->start_dpa + ent->len) {
> +                    /*
> +                     * The incoming extent covers a portion of an extent
> +                     * in the device extent list, remove only the overlapping
> +                     * portion, meaning
> +                     * 1. the portions that are not covered by the incoming
> +                     *    extent at both end of the original extent will become
> +                     *    new extents and inserted to the extent list; and
> +                     * 2. the original extent is removed from the extent list;
> +                     * 3. DC extent count is updated accordingly.
> +                     */
> +                    uint64_t ent_start_dpa = ent->start_dpa;
> +                    uint64_t ent_len = ent->len;
> +                    uint64_t len1 = dpa - ent_start_dpa;
> +                    uint64_t len2 = ent_start_dpa + ent_len - dpa - len;
> +
> +                    /*
> +                     * TODO: checking for possible extent overflow, will be
> +                     * moved into a dedicated function of detecting extent
> +                     * overflow.
> +                     */
> +                    if (len1 && len2 && ct3d->dc.total_extent_count ==
> +                        CXL_NUM_EXTENTS_SUPPORTED) {
> +                        return CXL_MBOX_RESOURCES_EXHAUSTED;
> +                    }
> +
> +                    found = true;
> +                    cxl_remove_extent_from_extent_list(extent_list, ent);
> +                    ct3d->dc.total_extent_count -= 1;
> +
> +                    if (len1) {
> +                        cxl_insert_extent_to_extent_list(extent_list,
> +                                                         ent_start_dpa, len1,
> +                                                         NULL, 0);
> +                        ct3d->dc.total_extent_count += 1;
> +                    }
> +                    if (len2) {
> +                        cxl_insert_extent_to_extent_list(extent_list, dpa + len,
> +                                                         len2, NULL, 0);
> +                        ct3d->dc.total_extent_count += 1;
> +                    }
> +                    break;
Maybe this makes sense after the support below is added, but at this
point in the series 
			return CXL_MBOX_SUCCESS;
then found isn't relevant so can drop that. Looks like you drop it later in the
series anyway.

> +                } else {
> +                    /*
> +                     * TODO: we reject the attempt to remove an extent that
> +                     * overlaps with multiple extents in the device for now,
> +                     * once the bitmap indicating whether a DPA range is
> +                     * covered by valid extents is introduced, will allow it.
> +                     */
> +                    return CXL_MBOX_INVALID_PA;
> +                }
> +            }
> +        }
> +
> +        if (!found) {
> +            /* Try to remove a non-existing extent. */
> +            return CXL_MBOX_INVALID_PA;
> +        }
> +    }
> +
> +    return CXL_MBOX_SUCCESS;
> +}
> +

>  static const struct cxl_cmd cxl_cmd_set_sw[256][256] = {
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index 102fa8151e..dccfaaad3a 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -678,6 +678,16 @@ static bool cxl_create_dc_regions(CXLType3Dev *ct3d, Error **errp)
>      return true;
>  }
>  
> +static void cxl_destroy_dc_regions(CXLType3Dev *ct3d)
> +{
> +    CXLDCExtent *ent;
> +
> +    while (!QTAILQ_EMPTY(&ct3d->dc.extents)) {
> +        ent = QTAILQ_FIRST(&ct3d->dc.extents);
> +        cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent);

Isn't this same a something like.
    QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node)) {
	cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent);
        //This wrapper is small enough I'd be tempted to just have the
        //code inline at the places it's called.

    }
> +    }
> +}



  reply	other threads:[~2024-03-06 17:28 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-04 19:33 [PATCH v5 00/13] Enabling DCD emulation support in Qemu nifan.cxl
2024-03-04 19:33 ` [PATCH v5 01/13] hw/cxl/cxl-mailbox-utils: Add dc_event_log_size field to output payload of identify memory device command nifan.cxl
2024-03-06 15:07   ` Jonathan Cameron
2024-03-06 15:07     ` Jonathan Cameron via
2024-03-04 19:33 ` [PATCH v5 02/13] hw/cxl/cxl-mailbox-utils: Add dynamic capacity region representative and mailbox command support nifan.cxl
2024-03-06 15:24   ` Jonathan Cameron
2024-03-06 15:24     ` Jonathan Cameron via
2024-03-04 19:33 ` [PATCH v5 03/13] include/hw/cxl/cxl_device: Rename mem_size as static_mem_size for type3 memory devices nifan.cxl
2024-03-06 15:39   ` Jonathan Cameron
2024-03-06 15:39     ` Jonathan Cameron via
2024-03-04 19:33 ` [PATCH v5 04/13] hw/mem/cxl_type3: Add support to create DC regions to " nifan.cxl
2024-03-06 15:48   ` Jonathan Cameron
2024-03-06 15:48     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 05/13] hw/mem/cxl-type3: Refactor ct3_build_cdat_entries_for_mr to take mr size insead of mr as argument nifan.cxl
2024-03-06 16:02   ` Jonathan Cameron
2024-03-06 16:02     ` Jonathan Cameron via
2024-03-06 16:03   ` Jonathan Cameron
2024-03-06 16:03     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 06/13] hw/mem/cxl_type3: Add host backend and address space handling for DC regions nifan.cxl
2024-03-06 16:28   ` Jonathan Cameron
2024-03-06 16:28     ` Jonathan Cameron via
2024-03-06 19:14     ` fan
2024-03-07 12:16       ` Jonathan Cameron
2024-03-07 12:16         ` Jonathan Cameron via
2024-03-07 23:34         ` fan
2024-03-14 20:43     ` fan
2024-03-04 19:34 ` [PATCH v5 07/13] hw/mem/cxl_type3: Add DC extent list representative and get DC extent list mailbox support nifan.cxl
2024-03-06 16:37   ` Jonathan Cameron
2024-03-06 16:37     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 08/13] hw/cxl/cxl-mailbox-utils: Add mailbox commands to support add/release dynamic capacity response nifan.cxl
2024-03-06 17:28   ` Jonathan Cameron [this message]
2024-03-06 17:28     ` Jonathan Cameron via
2024-03-06 21:39     ` fan
2024-03-07 12:20       ` Jonathan Cameron
2024-03-07 12:20         ` Jonathan Cameron via
2024-03-06 22:34     ` fan
2024-03-07 12:30       ` Jonathan Cameron
2024-03-07 12:30         ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 09/13] hw/cxl/events: Add qmp interfaces to add/release dynamic capacity extents nifan.cxl
2024-03-06 17:48   ` Jonathan Cameron
2024-03-06 17:48     ` Jonathan Cameron via
2024-03-06 23:15     ` fan
2024-03-07 12:45       ` Jonathan Cameron
2024-03-07 12:45         ` Jonathan Cameron via
2024-03-09  4:35         ` fan
2024-03-12 12:37           ` Jonathan Cameron
2024-03-12 12:37             ` Jonathan Cameron via
2024-03-12 16:27             ` fan
2024-03-06 23:36     ` fan
2024-03-07 12:47       ` Jonathan Cameron
2024-03-07 12:47         ` Jonathan Cameron via
2024-04-24 13:09   ` Markus Armbruster
2024-04-24 17:10     ` fan
2024-04-24 17:26       ` Markus Armbruster
2024-04-24 17:44         ` fan
2024-04-24 17:33     ` Ira Weiny
2024-04-26 15:55       ` Jonathan Cameron
2024-04-26 15:55         ` Jonathan Cameron via
2024-04-26 16:22         ` Gregory Price
2024-04-24 17:39     ` fan
2024-04-25  5:48       ` Markus Armbruster
2024-04-25 17:30         ` Ira Weiny
2024-04-26 16:00           ` Jonathan Cameron
2024-04-26 16:00             ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 10/13] hw/mem/cxl_type3: Add dpa range validation for accesses to DC regions nifan.cxl
2024-03-06 17:50   ` Jonathan Cameron
2024-03-06 17:50     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 11/13] hw/cxl/cxl-mailbox-utils: Add partial and superset extent release mailbox support nifan.cxl
2024-03-06 18:09   ` Jonathan Cameron
2024-03-06 18:09     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 12/13] hw/mem/cxl_type3: Allow to release partial extent and extent superset in QMP interface nifan.cxl
2024-03-06 18:14   ` Jonathan Cameron
2024-03-06 18:14     ` Jonathan Cameron via
2024-03-04 19:34 ` [PATCH v5 13/13] qapi/cxl.json: Add QMP interfaces to print out accepted and pending DC extents nifan.cxl
2024-03-05 16:09   ` Jonathan Cameron
2024-03-05 16:09     ` Jonathan Cameron via
2024-03-05 16:15     ` Daniel P. Berrangé
2024-03-05 17:09       ` fan
2024-03-05 17:14         ` Daniel P. Berrangé
2024-04-24 13:12           ` Markus Armbruster
2024-04-24 17:12             ` fan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240306172827.000052dc@Huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=Jorgen.Hansen@wdc.com \
    --cc=a.manzanares@samsung.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave@stgolabs.net \
    --cc=fan.ni@samsung.com \
    --cc=gregory.price@memverge.com \
    --cc=ira.weiny@intel.com \
    --cc=jim.harris@samsung.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=nifan.cxl@gmail.com \
    --cc=nmtadam.samsung@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=wj28.lee@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.