spi: spi-mem: Add devm_spi_mem_dirmap_{create,destroy}()
authorBoris Brezillon <bbrezillon@kernel.org>
Sat, 19 Jan 2019 15:04:12 +0000 (16:04 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 21 Jan 2019 17:58:12 +0000 (17:58 +0000)
Since direct mapping descriptors usually the same lifetime as the SPI
MEM device adding devm_ variants of the spi_mem_dirmap_{create,destroy}()
should greatly simplify error/remove path of spi-mem drivers making use
of the direct mapping API.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-mem.c
include/linux/spi/spi-mem.h

index 5217a5628be27e3f4edd2ca96547a2e4e20c83f3..08e326a124cc4bb18c0d0636c44af82bf0f97763 100644 (file)
@@ -551,6 +551,75 @@ void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc)
 }
 EXPORT_SYMBOL_GPL(spi_mem_dirmap_destroy);
 
+static void devm_spi_mem_dirmap_release(struct device *dev, void *res)
+{
+       struct spi_mem_dirmap_desc *desc = *(struct spi_mem_dirmap_desc **)res;
+
+       spi_mem_dirmap_destroy(desc);
+}
+
+/**
+ * devm_spi_mem_dirmap_create() - Create a direct mapping descriptor and attach
+ *                               it to a device
+ * @dev: device the dirmap desc will be attached to
+ * @mem: SPI mem device this direct mapping should be created for
+ * @info: direct mapping information
+ *
+ * devm_ variant of the spi_mem_dirmap_create() function. See
+ * spi_mem_dirmap_create() for more details.
+ *
+ * Return: a valid pointer in case of success, and ERR_PTR() otherwise.
+ */
+struct spi_mem_dirmap_desc *
+devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem,
+                          const struct spi_mem_dirmap_info *info)
+{
+       struct spi_mem_dirmap_desc **ptr, *desc;
+
+       ptr = devres_alloc(devm_spi_mem_dirmap_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       desc = spi_mem_dirmap_create(mem, info);
+       if (IS_ERR(desc)) {
+               devres_free(ptr);
+       } else {
+               *ptr = desc;
+               devres_add(dev, ptr);
+       }
+
+       return desc;
+}
+EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_create);
+
+static int devm_spi_mem_dirmap_match(struct device *dev, void *res, void *data)
+{
+        struct spi_mem_dirmap_desc **ptr = res;
+
+        if (WARN_ON(!ptr || !*ptr))
+                return 0;
+
+       return *ptr == data;
+}
+
+/**
+ * devm_spi_mem_dirmap_destroy() - Destroy a direct mapping descriptor attached
+ *                                to a device
+ * @dev: device the dirmap desc is attached to
+ * @desc: the direct mapping descriptor to destroy
+ *
+ * devm_ variant of the spi_mem_dirmap_destroy() function. See
+ * spi_mem_dirmap_destroy() for more details.
+ */
+void devm_spi_mem_dirmap_destroy(struct device *dev,
+                                struct spi_mem_dirmap_desc *desc)
+{
+       devres_release(dev, devm_spi_mem_dirmap_release,
+                      devm_spi_mem_dirmap_match, desc);
+}
+EXPORT_SYMBOL_GPL(devm_spi_mem_dirmap_destroy);
+
 /**
  * spi_mem_dirmap_dirmap_read() - Read data through a direct mapping
  * @desc: direct mapping descriptor
index 3fe24500c5ee957d104f319cd3246e0abccf3a34..3703d0dcac2e8f674a0de021676aa294947bc43a 100644 (file)
@@ -330,6 +330,11 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
                            u64 offs, size_t len, void *buf);
 ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
                             u64 offs, size_t len, const void *buf);
+struct spi_mem_dirmap_desc *
+devm_spi_mem_dirmap_create(struct device *dev, struct spi_mem *mem,
+                          const struct spi_mem_dirmap_info *info);
+void devm_spi_mem_dirmap_destroy(struct device *dev,
+                                struct spi_mem_dirmap_desc *desc);
 
 int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
                                       struct module *owner);