diff mbox series

[v2,32/36] soc: fsl: qe: Add resource-managed muram allocators

Message ID 20240808071132.149251-33-herve.codina@bootlin.com (mailing list archive)
State New, archived
Headers show
Series soc: fsl: Add support for QUICC Engine TSA and QMC | expand

Commit Message

Herve Codina Aug. 8, 2024, 7:11 a.m. UTC
Introduce devm_cpm_muram_alloc() and devm_cpm_muram_alloc_fixed(), the
resource-managed version of cpm_muram_alloc and cpm_muram_alloc_fixed().

These resource-managed versions simplify the user avoiding the need to
call cpm_muram_free(). Indeed, the allocated area returned by these
functions will be automatically freed on driver detach.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
---
 drivers/soc/fsl/qe/qe_common.c | 80 ++++++++++++++++++++++++++++++++++
 include/soc/fsl/qe/qe.h        | 22 +++++++++-
 2 files changed, 101 insertions(+), 1 deletion(-)

Comments

Christophe Leroy Aug. 23, 2024, 8:13 a.m. UTC | #1
Le 08/08/2024 à 09:11, Herve Codina a écrit :
> Introduce devm_cpm_muram_alloc() and devm_cpm_muram_alloc_fixed(), the
> resource-managed version of cpm_muram_alloc and cpm_muram_alloc_fixed().
> 
> These resource-managed versions simplify the user avoiding the need to
> call cpm_muram_free(). Indeed, the allocated area returned by these
> functions will be automatically freed on driver detach.
> 
> Signed-off-by: Herve Codina <herve.codina@bootlin.com>

Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>

> ---
>   drivers/soc/fsl/qe/qe_common.c | 80 ++++++++++++++++++++++++++++++++++
>   include/soc/fsl/qe/qe.h        | 22 +++++++++-
>   2 files changed, 101 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c
> index a877347d37d3..02c29f5f86d3 100644
> --- a/drivers/soc/fsl/qe/qe_common.c
> +++ b/drivers/soc/fsl/qe/qe_common.c
> @@ -13,6 +13,7 @@
>    * 2006 (c) MontaVista Software, Inc.
>    * Vitaly Bordug <vbordug@ru.mvista.com>
>    */
> +#include <linux/device.h>
>   #include <linux/genalloc.h>
>   #include <linux/init.h>
>   #include <linux/list.h>
> @@ -187,6 +188,49 @@ void cpm_muram_free(s32 offset)
>   }
>   EXPORT_SYMBOL(cpm_muram_free);
>   
> +static void devm_cpm_muram_release(struct device *dev, void *res)
> +{
> +	s32 *info = res;
> +
> +	cpm_muram_free(*info);
> +}
> +
> +/**
> + * devm_cpm_muram_alloc - Resource-managed cpm_muram_alloc
> + * @dev: Device to allocate memory for
> + * @size: number of bytes to allocate
> + * @align: requested alignment, in bytes
> + *
> + * This function returns a non-negative offset into the muram area, or
> + * a negative errno on failure as cpm_muram_alloc() does.
> + * Use cpm_muram_addr() to get the virtual address of the area.
> + *
> + * Compare against cpm_muram_alloc(), the memory allocated by this
> + * resource-managed version is automatically freed on driver detach and so,
> + * cpm_muram_free() must not be called to release the allocated memory.
> + */
> +s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
> +			 unsigned long align)
> +{
> +	s32 info;
> +	s32 *dr;
> +
> +	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
> +	if (!dr)
> +		return -ENOMEM;
> +
> +	info = cpm_muram_alloc(size, align);
> +	if (info >= 0) {
> +		*dr = info;
> +		devres_add(dev, dr);
> +	} else {
> +		devres_free(dr);
> +	}
> +
> +	return info;
> +}
> +EXPORT_SYMBOL(devm_cpm_muram_alloc);
> +
>   /*
>    * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
>    * @offset: offset of allocation start address
> @@ -211,6 +255,42 @@ s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
>   }
>   EXPORT_SYMBOL(cpm_muram_alloc_fixed);
>   
> +/**
> + * devm_cpm_muram_alloc_fixed - Resource-managed cpm_muram_alloc_fixed
> + * @dev: Device to allocate memory for
> + * @offset: offset of allocation start address
> + * @size: number of bytes to allocate
> + *
> + * This function returns a non-negative offset into the muram area, or
> + * a negative errno on failure as cpm_muram_alloc_fixed() does.
> + * Use cpm_muram_addr() to get the virtual address of the area.
> + *
> + * Compare against cpm_muram_alloc_fixed(), the memory allocated by this
> + * resource-managed version is automatically freed on driver detach and so,
> + * cpm_muram_free() must not be called to release the allocated memory.
> + */
> +s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
> +			       unsigned long size)
> +{
> +	s32 info;
> +	s32 *dr;
> +
> +	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
> +	if (!dr)
> +		return -ENOMEM;
> +
> +	info = cpm_muram_alloc_fixed(offset, size);
> +	if (info >= 0) {
> +		*dr = info;
> +		devres_add(dev, dr);
> +	} else {
> +		devres_free(dr);
> +	}
> +
> +	return info;
> +}
> +EXPORT_SYMBOL(devm_cpm_muram_alloc_fixed);
> +
>   /**
>    * cpm_muram_addr - turn a muram offset into a virtual address
>    * @offset: muram offset to convert
> diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h
> index af793f2a0ec4..629835b6c71d 100644
> --- a/include/soc/fsl/qe/qe.h
> +++ b/include/soc/fsl/qe/qe.h
> @@ -23,6 +23,8 @@
>   #include <linux/of_address.h>
>   #include <linux/types.h>
>   
> +struct device;
> +
>   #define QE_NUM_OF_SNUM	256	/* There are 256 serial number in QE */
>   #define QE_NUM_OF_BRGS	16
>   #define QE_NUM_OF_PORTS	1024
> @@ -93,8 +95,12 @@ int cpm_muram_init(void);
>   
>   #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
>   s32 cpm_muram_alloc(unsigned long size, unsigned long align);
> +s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
> +			 unsigned long align);
>   void cpm_muram_free(s32 offset);
>   s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
> +s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
> +			       unsigned long size);
>   void __iomem *cpm_muram_addr(unsigned long offset);
>   unsigned long cpm_muram_offset(const void __iomem *addr);
>   dma_addr_t cpm_muram_dma(void __iomem *addr);
> @@ -106,6 +112,12 @@ static inline s32 cpm_muram_alloc(unsigned long size,
>   	return -ENOSYS;
>   }
>   
> +static inline s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
> +				       unsigned long align)
> +{
> +	return -ENOSYS;
> +}
> +
>   static inline void cpm_muram_free(s32 offset)
>   {
>   }
> @@ -116,6 +128,13 @@ static inline s32 cpm_muram_alloc_fixed(unsigned long offset,
>   	return -ENOSYS;
>   }
>   
> +static inline s32 devm_cpm_muram_alloc_fixed(struct device *dev,
> +					     unsigned long offset,
> +					     unsigned long size)
> +{
> +	return -ENOSYS;
> +}
> +
>   static inline void __iomem *cpm_muram_addr(unsigned long offset)
>   {
>   	return NULL;
> @@ -172,7 +191,6 @@ static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
>   /*
>    * Pin multiplexing functions.
>    */
> -struct device;
>   struct qe_pin;
>   #ifdef CONFIG_QE_GPIO
>   extern struct qe_pin *qe_pin_request(struct device *dev, int index);
> @@ -233,7 +251,9 @@ static inline int qe_alive_during_sleep(void)
>   /* we actually use cpm_muram implementation, define this for convenience */
>   #define qe_muram_init cpm_muram_init
>   #define qe_muram_alloc cpm_muram_alloc
> +#define devm_qe_muram_alloc devm_cpm_muram_alloc
>   #define qe_muram_alloc_fixed cpm_muram_alloc_fixed
> +#define devm_qe_muram_alloc_fixed devm_cpm_muram_alloc_fixed
>   #define qe_muram_free cpm_muram_free
>   #define qe_muram_addr cpm_muram_addr
>   #define qe_muram_offset cpm_muram_offset
diff mbox series

Patch

diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c
index a877347d37d3..02c29f5f86d3 100644
--- a/drivers/soc/fsl/qe/qe_common.c
+++ b/drivers/soc/fsl/qe/qe_common.c
@@ -13,6 +13,7 @@ 
  * 2006 (c) MontaVista Software, Inc.
  * Vitaly Bordug <vbordug@ru.mvista.com>
  */
+#include <linux/device.h>
 #include <linux/genalloc.h>
 #include <linux/init.h>
 #include <linux/list.h>
@@ -187,6 +188,49 @@  void cpm_muram_free(s32 offset)
 }
 EXPORT_SYMBOL(cpm_muram_free);
 
+static void devm_cpm_muram_release(struct device *dev, void *res)
+{
+	s32 *info = res;
+
+	cpm_muram_free(*info);
+}
+
+/**
+ * devm_cpm_muram_alloc - Resource-managed cpm_muram_alloc
+ * @dev: Device to allocate memory for
+ * @size: number of bytes to allocate
+ * @align: requested alignment, in bytes
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
+			 unsigned long align)
+{
+	s32 info;
+	s32 *dr;
+
+	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	info = cpm_muram_alloc(size, align);
+	if (info >= 0) {
+		*dr = info;
+		devres_add(dev, dr);
+	} else {
+		devres_free(dr);
+	}
+
+	return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc);
+
 /*
  * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
  * @offset: offset of allocation start address
@@ -211,6 +255,42 @@  s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
 }
 EXPORT_SYMBOL(cpm_muram_alloc_fixed);
 
+/**
+ * devm_cpm_muram_alloc_fixed - Resource-managed cpm_muram_alloc_fixed
+ * @dev: Device to allocate memory for
+ * @offset: offset of allocation start address
+ * @size: number of bytes to allocate
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc_fixed() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc_fixed(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
+			       unsigned long size)
+{
+	s32 info;
+	s32 *dr;
+
+	dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	info = cpm_muram_alloc_fixed(offset, size);
+	if (info >= 0) {
+		*dr = info;
+		devres_add(dev, dr);
+	} else {
+		devres_free(dr);
+	}
+
+	return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc_fixed);
+
 /**
  * cpm_muram_addr - turn a muram offset into a virtual address
  * @offset: muram offset to convert
diff --git a/include/soc/fsl/qe/qe.h b/include/soc/fsl/qe/qe.h
index af793f2a0ec4..629835b6c71d 100644
--- a/include/soc/fsl/qe/qe.h
+++ b/include/soc/fsl/qe/qe.h
@@ -23,6 +23,8 @@ 
 #include <linux/of_address.h>
 #include <linux/types.h>
 
+struct device;
+
 #define QE_NUM_OF_SNUM	256	/* There are 256 serial number in QE */
 #define QE_NUM_OF_BRGS	16
 #define QE_NUM_OF_PORTS	1024
@@ -93,8 +95,12 @@  int cpm_muram_init(void);
 
 #if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
 s32 cpm_muram_alloc(unsigned long size, unsigned long align);
+s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
+			 unsigned long align);
 void cpm_muram_free(s32 offset);
 s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
+s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
+			       unsigned long size);
 void __iomem *cpm_muram_addr(unsigned long offset);
 unsigned long cpm_muram_offset(const void __iomem *addr);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
@@ -106,6 +112,12 @@  static inline s32 cpm_muram_alloc(unsigned long size,
 	return -ENOSYS;
 }
 
+static inline s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
+				       unsigned long align)
+{
+	return -ENOSYS;
+}
+
 static inline void cpm_muram_free(s32 offset)
 {
 }
@@ -116,6 +128,13 @@  static inline s32 cpm_muram_alloc_fixed(unsigned long offset,
 	return -ENOSYS;
 }
 
+static inline s32 devm_cpm_muram_alloc_fixed(struct device *dev,
+					     unsigned long offset,
+					     unsigned long size)
+{
+	return -ENOSYS;
+}
+
 static inline void __iomem *cpm_muram_addr(unsigned long offset)
 {
 	return NULL;
@@ -172,7 +191,6 @@  static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
 /*
  * Pin multiplexing functions.
  */
-struct device;
 struct qe_pin;
 #ifdef CONFIG_QE_GPIO
 extern struct qe_pin *qe_pin_request(struct device *dev, int index);
@@ -233,7 +251,9 @@  static inline int qe_alive_during_sleep(void)
 /* we actually use cpm_muram implementation, define this for convenience */
 #define qe_muram_init cpm_muram_init
 #define qe_muram_alloc cpm_muram_alloc
+#define devm_qe_muram_alloc devm_cpm_muram_alloc
 #define qe_muram_alloc_fixed cpm_muram_alloc_fixed
+#define devm_qe_muram_alloc_fixed devm_cpm_muram_alloc_fixed
 #define qe_muram_free cpm_muram_free
 #define qe_muram_addr cpm_muram_addr
 #define qe_muram_offset cpm_muram_offset