diff mbox series

[05/26] cxl/core: Simplify cxl_dpa_set_mode()

Message ID 20240324-dcd-type2-upstream-v1-5-b7b00d623625@intel.com (mailing list archive)
State New, archived
Headers show
Series DCD: Add support for Dynamic Capacity Devices (DCD) | expand

Commit Message

Ira Weiny March 24, 2024, 11:18 p.m. UTC
cxl_dpa_set_mode() checks the mode for validity two times, once outside
of the DPA RW semaphore and again within.  The function is not in a
critical path.  Prior to Dynamic Capacity the extra check was not much
of an issue.  The addition of DC modes increases the complexity of
the check.

Simplify the mode check before adding the more complex DC modes.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>

---
Changes for v1:
[iweiny: new patch]
[Jonathan: based on getting rid of the loop in cxl_dpa_set_mode]
[Jonathan: standardize on resource_size() == 0]
---
 drivers/cxl/core/hdm.c | 45 ++++++++++++++++++---------------------------
 1 file changed, 18 insertions(+), 27 deletions(-)

Comments

Jonathan Cameron March 25, 2024, 5:46 p.m. UTC | #1
On Sun, 24 Mar 2024 16:18:08 -0700
Ira Weiny <ira.weiny@intel.com> wrote:

> cxl_dpa_set_mode() checks the mode for validity two times, once outside
> of the DPA RW semaphore and again within.  The function is not in a
> critical path.  Prior to Dynamic Capacity the extra check was not much
> of an issue.  The addition of DC modes increases the complexity of
> the check.
> 
> Simplify the mode check before adding the more complex DC modes.
> 
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>

Nice. Maybe drag this earlier in series so it could potentially be
picked up as a cleanup?  Same with patch 2 potentially.
If Dave is fine with doing that sort of precursor patches going
earlier, it will save carrying quite so many in this series for
future versions (and make it look less terrifying :)

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Davidlohr Bueso March 25, 2024, 9:38 p.m. UTC | #2
On Sun, 24 Mar 2024, Ira Weiny wrote:

>cxl_dpa_set_mode() checks the mode for validity two times, once outside
>of the DPA RW semaphore and again within.  The function is not in a
>critical path.  Prior to Dynamic Capacity the extra check was not much
>of an issue.  The addition of DC modes increases the complexity of
>the check.

I agree (also to pick this up regardless of dcd work).

>
>Simplify the mode check before adding the more complex DC modes.

Reviewed-by: Davidlohr Bueso <dave@stgolabs.net>

>Signed-off-by: Ira Weiny <ira.weiny@intel.com>
>
>---
>Changes for v1:
>[iweiny: new patch]
>[Jonathan: based on getting rid of the loop in cxl_dpa_set_mode]
>[Jonathan: standardize on resource_size() == 0]
>---
> drivers/cxl/core/hdm.c | 45 ++++++++++++++++++---------------------------
> 1 file changed, 18 insertions(+), 27 deletions(-)
>
>diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
>index 7d97790b893d..66b8419fd0c3 100644
>--- a/drivers/cxl/core/hdm.c
>+++ b/drivers/cxl/core/hdm.c
>@@ -411,44 +411,35 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
>	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
>	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>	struct device *dev = &cxled->cxld.dev;
>-	int rc;
>
>+	guard(rwsem_write)(&cxl_dpa_rwsem);
>+	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
>+		return -EBUSY;
>+
>+	/*
>+	 * Check that the mode is supported by the current partition
>+	 * configuration
>+	 */
>	switch (mode) {
>	case CXL_DECODER_RAM:
>+		if (!resource_size(&cxlds->ram_res)) {
>+			dev_dbg(dev, "no available ram capacity\n");
>+			return -ENXIO;
>+		}
>+		break;
>	case CXL_DECODER_PMEM:
>+		if (!resource_size(&cxlds->pmem_res)) {
>+			dev_dbg(dev, "no available pmem capacity\n");
>+			return -ENXIO;
>+		}
>		break;
>	default:
>		dev_dbg(dev, "unsupported mode: %d\n", mode);
>		return -EINVAL;
>	}
>
>-	down_write(&cxl_dpa_rwsem);
>-	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
>-		rc = -EBUSY;
>-		goto out;
>-	}
>-
>-	/*
>-	 * Only allow modes that are supported by the current partition
>-	 * configuration
>-	 */
>-	if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
>-		dev_dbg(dev, "no available pmem capacity\n");
>-		rc = -ENXIO;
>-		goto out;
>-	}
>-	if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
>-		dev_dbg(dev, "no available ram capacity\n");
>-		rc = -ENXIO;
>-		goto out;
>-	}
>-
>	cxled->mode = mode;
>-	rc = 0;
>-out:
>-	up_write(&cxl_dpa_rwsem);
>-
>-	return rc;
>+	return 0;
> }
>
> int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
>
>--
>2.44.0
>
fan March 26, 2024, 4:25 p.m. UTC | #3
On Sun, Mar 24, 2024 at 04:18:08PM -0700, Ira Weiny wrote:
> cxl_dpa_set_mode() checks the mode for validity two times, once outside
> of the DPA RW semaphore and again within.  The function is not in a
> critical path.  Prior to Dynamic Capacity the extra check was not much
> of an issue.  The addition of DC modes increases the complexity of
> the check.
> 
> Simplify the mode check before adding the more complex DC modes.
> 
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> 

Reviewed-by: Fan Ni <fan.ni@samsung.com>

> ---
> Changes for v1:
> [iweiny: new patch]
> [Jonathan: based on getting rid of the loop in cxl_dpa_set_mode]
> [Jonathan: standardize on resource_size() == 0]
> ---
>  drivers/cxl/core/hdm.c | 45 ++++++++++++++++++---------------------------
>  1 file changed, 18 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 7d97790b893d..66b8419fd0c3 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -411,44 +411,35 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
>  	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>  	struct device *dev = &cxled->cxld.dev;
> -	int rc;
>  
> +	guard(rwsem_write)(&cxl_dpa_rwsem);
> +	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
> +		return -EBUSY;
> +
> +	/*
> +	 * Check that the mode is supported by the current partition
> +	 * configuration
> +	 */
>  	switch (mode) {
>  	case CXL_DECODER_RAM:
> +		if (!resource_size(&cxlds->ram_res)) {
> +			dev_dbg(dev, "no available ram capacity\n");
> +			return -ENXIO;
> +		}
> +		break;
>  	case CXL_DECODER_PMEM:
> +		if (!resource_size(&cxlds->pmem_res)) {
> +			dev_dbg(dev, "no available pmem capacity\n");
> +			return -ENXIO;
> +		}
>  		break;
>  	default:
>  		dev_dbg(dev, "unsupported mode: %d\n", mode);
>  		return -EINVAL;
>  	}
>  
> -	down_write(&cxl_dpa_rwsem);
> -	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
> -		rc = -EBUSY;
> -		goto out;
> -	}
> -
> -	/*
> -	 * Only allow modes that are supported by the current partition
> -	 * configuration
> -	 */
> -	if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
> -		dev_dbg(dev, "no available pmem capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -	if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
> -		dev_dbg(dev, "no available ram capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -
>  	cxled->mode = mode;
> -	rc = 0;
> -out:
> -	up_write(&cxl_dpa_rwsem);
> -
> -	return rc;
> +	return 0;
>  }
>  
>  int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
> 
> -- 
> 2.44.0
>
Dave Jiang March 26, 2024, 5:46 p.m. UTC | #4
On 3/24/24 4:18 PM, Ira Weiny wrote:
> cxl_dpa_set_mode() checks the mode for validity two times, once outside
> of the DPA RW semaphore and again within.  The function is not in a
> critical path.  Prior to Dynamic Capacity the extra check was not much
> of an issue.  The addition of DC modes increases the complexity of
> the check.
> 
> Simplify the mode check before adding the more complex DC modes.

I would augment this by saying simplify "by using scope-based resource menagement".
> 
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> 
> ---
> Changes for v1:
> [iweiny: new patch]
> [Jonathan: based on getting rid of the loop in cxl_dpa_set_mode]
> [Jonathan: standardize on resource_size() == 0]
> ---
>  drivers/cxl/core/hdm.c | 45 ++++++++++++++++++---------------------------
>  1 file changed, 18 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 7d97790b893d..66b8419fd0c3 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -411,44 +411,35 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
>  	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>  	struct device *dev = &cxled->cxld.dev;
> -	int rc;
>  
> +	guard(rwsem_write)(&cxl_dpa_rwsem);
> +	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
> +		return -EBUSY;
> +
> +	/*
> +	 * Check that the mode is supported by the current partition
> +	 * configuration
> +	 */
>  	switch (mode) {
>  	case CXL_DECODER_RAM:
> +		if (!resource_size(&cxlds->ram_res)) {
> +			dev_dbg(dev, "no available ram capacity\n");
> +			return -ENXIO;
> +		}
> +		break;
>  	case CXL_DECODER_PMEM:
> +		if (!resource_size(&cxlds->pmem_res)) {
> +			dev_dbg(dev, "no available pmem capacity\n");
> +			return -ENXIO;
> +		}
>  		break;
>  	default:
>  		dev_dbg(dev, "unsupported mode: %d\n", mode);
>  		return -EINVAL;
>  	}
>  
> -	down_write(&cxl_dpa_rwsem);
> -	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
> -		rc = -EBUSY;
> -		goto out;
> -	}
> -
> -	/*
> -	 * Only allow modes that are supported by the current partition
> -	 * configuration
> -	 */
> -	if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
> -		dev_dbg(dev, "no available pmem capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -	if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
> -		dev_dbg(dev, "no available ram capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -
>  	cxled->mode = mode;
> -	rc = 0;
> -out:
> -	up_write(&cxl_dpa_rwsem);
> -
> -	return rc;
> +	return 0;
>  }
>  
>  int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
>
Ira Weiny April 5, 2024, 7:21 p.m. UTC | #5
Dave Jiang wrote:
> 
> 
> On 3/24/24 4:18 PM, Ira Weiny wrote:
> > cxl_dpa_set_mode() checks the mode for validity two times, once outside
> > of the DPA RW semaphore and again within.  The function is not in a
> > critical path.  Prior to Dynamic Capacity the extra check was not much
> > of an issue.  The addition of DC modes increases the complexity of
> > the check.
> > 
> > Simplify the mode check before adding the more complex DC modes.
> 
> I would augment this by saying simplify "by using scope-based resource menagement".

However, using the guard cleanup is not really the simplification here.  It is
more about checking the mode a single time.

That said I will change this to:

Simplify the mode check and convert to use of a cleanup guard.

Ira
Dave Jiang April 6, 2024, 12:02 a.m. UTC | #6
On 4/5/24 12:21 PM, Ira Weiny wrote:
> Dave Jiang wrote:
>>
>>
>> On 3/24/24 4:18 PM, Ira Weiny wrote:
>>> cxl_dpa_set_mode() checks the mode for validity two times, once outside
>>> of the DPA RW semaphore and again within.  The function is not in a
>>> critical path.  Prior to Dynamic Capacity the extra check was not much
>>> of an issue.  The addition of DC modes increases the complexity of
>>> the check.
>>>
>>> Simplify the mode check before adding the more complex DC modes.
>>
>> I would augment this by saying simplify "by using scope-based resource menagement".
> 
> However, using the guard cleanup is not really the simplification here.  It is
> more about checking the mode a single time.
> 
> That said I will change this to:
> 
> Simplify the mode check and convert to use of a cleanup guard.

Ok

> 
> Ira
Alison Schofield April 9, 2024, 12:43 a.m. UTC | #7
On Sun, Mar 24, 2024 at 04:18:08PM -0700, Ira Weiny wrote:
> cxl_dpa_set_mode() checks the mode for validity two times, once outside
> of the DPA RW semaphore and again within.

Not true. It only checks mode once before the lock. It checks for
capacity after the lock. If it didn't check mode before the lock,
then unsupported modes would fall through.

> The function is not in a critical path.

Implying what here?  OK to check twice (even though it wasn't)
or OK to expand scope of locking.

> Prior to Dynamic Capacity the extra check was not much
> of an issue.  The addition of DC modes increases the complexity of
> the check.
> 
> Simplify the mode check before adding the more complex DC modes.
> 

The addition of the DC mode check doesn't seem complex.

Pardon my picking at the words, but if you'd like to refactor the
function, just say so. The final result is a bit more readable, but
also adding the DC mode checks without refactoring would read fine
also.

and...a bit spacing nit below -

> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> 
> ---
> Changes for v1:
> [iweiny: new patch]
> [Jonathan: based on getting rid of the loop in cxl_dpa_set_mode]
> [Jonathan: standardize on resource_size() == 0]
> ---
>  drivers/cxl/core/hdm.c | 45 ++++++++++++++++++---------------------------
>  1 file changed, 18 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index 7d97790b893d..66b8419fd0c3 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -411,44 +411,35 @@ int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
>  	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
>  	struct cxl_dev_state *cxlds = cxlmd->cxlds;
>  	struct device *dev = &cxled->cxld.dev;
> -	int rc;
>  
> +	guard(rwsem_write)(&cxl_dpa_rwsem);
> +	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
> +		return -EBUSY;
> +
> +	/*
> +	 * Check that the mode is supported by the current partition
> +	 * configuration
> +	 */
>  	switch (mode) {
>  	case CXL_DECODER_RAM:
> +		if (!resource_size(&cxlds->ram_res)) {
> +			dev_dbg(dev, "no available ram capacity\n");
> +			return -ENXIO;
> +		}
> +		break;
>  	case CXL_DECODER_PMEM:
> +		if (!resource_size(&cxlds->pmem_res)) {
> +			dev_dbg(dev, "no available pmem capacity\n");
> +			return -ENXIO;
> +		}
>  		break;
>  	default:
>  		dev_dbg(dev, "unsupported mode: %d\n", mode);
>  		return -EINVAL;
>  	}
>  

delete extra line

> -	down_write(&cxl_dpa_rwsem);
> -	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
> -		rc = -EBUSY;
> -		goto out;
> -	}
> -
> -	/*
> -	 * Only allow modes that are supported by the current partition
> -	 * configuration
> -	 */
> -	if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
> -		dev_dbg(dev, "no available pmem capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -	if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
> -		dev_dbg(dev, "no available ram capacity\n");
> -		rc = -ENXIO;
> -		goto out;
> -	}
> -
>  	cxled->mode = mode;
> -	rc = 0;
> -out:
> -	up_write(&cxl_dpa_rwsem);
> -
> -	return rc;
insert blank line
> +	return 0;
>  }
>  
>  int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)
> 
> -- 
> 2.44.0
>
diff mbox series

Patch

diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index 7d97790b893d..66b8419fd0c3 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -411,44 +411,35 @@  int cxl_dpa_set_mode(struct cxl_endpoint_decoder *cxled,
 	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
 	struct device *dev = &cxled->cxld.dev;
-	int rc;
 
+	guard(rwsem_write)(&cxl_dpa_rwsem);
+	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE)
+		return -EBUSY;
+
+	/*
+	 * Check that the mode is supported by the current partition
+	 * configuration
+	 */
 	switch (mode) {
 	case CXL_DECODER_RAM:
+		if (!resource_size(&cxlds->ram_res)) {
+			dev_dbg(dev, "no available ram capacity\n");
+			return -ENXIO;
+		}
+		break;
 	case CXL_DECODER_PMEM:
+		if (!resource_size(&cxlds->pmem_res)) {
+			dev_dbg(dev, "no available pmem capacity\n");
+			return -ENXIO;
+		}
 		break;
 	default:
 		dev_dbg(dev, "unsupported mode: %d\n", mode);
 		return -EINVAL;
 	}
 
-	down_write(&cxl_dpa_rwsem);
-	if (cxled->cxld.flags & CXL_DECODER_F_ENABLE) {
-		rc = -EBUSY;
-		goto out;
-	}
-
-	/*
-	 * Only allow modes that are supported by the current partition
-	 * configuration
-	 */
-	if (mode == CXL_DECODER_PMEM && !resource_size(&cxlds->pmem_res)) {
-		dev_dbg(dev, "no available pmem capacity\n");
-		rc = -ENXIO;
-		goto out;
-	}
-	if (mode == CXL_DECODER_RAM && !resource_size(&cxlds->ram_res)) {
-		dev_dbg(dev, "no available ram capacity\n");
-		rc = -ENXIO;
-		goto out;
-	}
-
 	cxled->mode = mode;
-	rc = 0;
-out:
-	up_write(&cxl_dpa_rwsem);
-
-	return rc;
+	return 0;
 }
 
 int cxl_dpa_alloc(struct cxl_endpoint_decoder *cxled, unsigned long long size)