|
@@ -34,6 +34,8 @@
|
|
|
#include <linux/rculist.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/genalloc.h>
|
|
|
+#include <linux/of_address.h>
|
|
|
+#include <linux/of_device.h>
|
|
|
|
|
|
static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set)
|
|
|
{
|
|
@@ -480,3 +482,82 @@ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
|
|
|
return start_bit;
|
|
|
}
|
|
|
EXPORT_SYMBOL(gen_pool_best_fit);
|
|
|
+
|
|
|
+static void devm_gen_pool_release(struct device *dev, void *res)
|
|
|
+{
|
|
|
+ gen_pool_destroy(*(struct gen_pool **)res);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * devm_gen_pool_create - managed gen_pool_create
|
|
|
+ * @dev: device that provides the gen_pool
|
|
|
+ * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents
|
|
|
+ * @nid: node id of the node the pool structure should be allocated on, or -1
|
|
|
+ *
|
|
|
+ * Create a new special memory pool that can be used to manage special purpose
|
|
|
+ * memory not managed by the regular kmalloc/kfree interface. The pool will be
|
|
|
+ * automatically destroyed by the device management code.
|
|
|
+ */
|
|
|
+struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order,
|
|
|
+ int nid)
|
|
|
+{
|
|
|
+ struct gen_pool **ptr, *pool;
|
|
|
+
|
|
|
+ ptr = devres_alloc(devm_gen_pool_release, sizeof(*ptr), GFP_KERNEL);
|
|
|
+
|
|
|
+ pool = gen_pool_create(min_alloc_order, nid);
|
|
|
+ if (pool) {
|
|
|
+ *ptr = pool;
|
|
|
+ devres_add(dev, ptr);
|
|
|
+ } else {
|
|
|
+ devres_free(ptr);
|
|
|
+ }
|
|
|
+
|
|
|
+ return pool;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dev_get_gen_pool - Obtain the gen_pool (if any) for a device
|
|
|
+ * @dev: device to retrieve the gen_pool from
|
|
|
+ * @name: Optional name for the gen_pool, usually NULL
|
|
|
+ *
|
|
|
+ * Returns the gen_pool for the device if one is present, or NULL.
|
|
|
+ */
|
|
|
+struct gen_pool *dev_get_gen_pool(struct device *dev)
|
|
|
+{
|
|
|
+ struct gen_pool **p = devres_find(dev, devm_gen_pool_release, NULL,
|
|
|
+ NULL);
|
|
|
+
|
|
|
+ if (!p)
|
|
|
+ return NULL;
|
|
|
+ return *p;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(dev_get_gen_pool);
|
|
|
+
|
|
|
+#ifdef CONFIG_OF
|
|
|
+/**
|
|
|
+ * of_get_named_gen_pool - find a pool by phandle property
|
|
|
+ * @np: device node
|
|
|
+ * @propname: property name containing phandle(s)
|
|
|
+ * @index: index into the phandle array
|
|
|
+ *
|
|
|
+ * Returns the pool that contains the chunk starting at the physical
|
|
|
+ * address of the device tree node pointed at by the phandle property,
|
|
|
+ * or NULL if not found.
|
|
|
+ */
|
|
|
+struct gen_pool *of_get_named_gen_pool(struct device_node *np,
|
|
|
+ const char *propname, int index)
|
|
|
+{
|
|
|
+ struct platform_device *pdev;
|
|
|
+ struct device_node *np_pool;
|
|
|
+
|
|
|
+ np_pool = of_parse_phandle(np, propname, index);
|
|
|
+ if (!np_pool)
|
|
|
+ return NULL;
|
|
|
+ pdev = of_find_device_by_node(np_pool);
|
|
|
+ if (!pdev)
|
|
|
+ return NULL;
|
|
|
+ return dev_get_gen_pool(&pdev->dev);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(of_get_named_gen_pool);
|
|
|
+#endif /* CONFIG_OF */
|