Merge 3.16-rc4 into driver-core-next
We want the lz* fixes here to do more work with them.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 1525e30..de6bc8c 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -278,7 +278,6 @@
devm_ioremap_nocache()
devm_iounmap()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
- devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
pcim_iomap()
pcim_iounmap()
pcim_iomap_table() : array of mapped addresses indexed by BAR
diff --git a/drivers/base/component.c b/drivers/base/component.c
index c477899..b4236dae 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -18,6 +18,15 @@
#include <linux/mutex.h>
#include <linux/slab.h>
+struct component_match {
+ size_t alloc;
+ size_t num;
+ struct {
+ void *data;
+ int (*fn)(struct device *, void *);
+ } compare[0];
+};
+
struct master {
struct list_head node;
struct list_head components;
@@ -25,6 +34,7 @@
const struct component_master_ops *ops;
struct device *dev;
+ struct component_match *match;
};
struct component {
@@ -69,6 +79,11 @@
c->master = NULL;
}
+/*
+ * Add a component to a master, finding the component via the compare
+ * function and compare data. This is safe to call for duplicate matches
+ * and will not result in the same component being added multiple times.
+ */
int component_master_add_child(struct master *master,
int (*compare)(struct device *, void *), void *compare_data)
{
@@ -76,11 +91,12 @@
int ret = -ENXIO;
list_for_each_entry(c, &component_list, node) {
- if (c->master)
+ if (c->master && c->master != master)
continue;
if (compare(c->dev, compare_data)) {
- component_attach_master(master, c);
+ if (!c->master)
+ component_attach_master(master, c);
ret = 0;
break;
}
@@ -90,6 +106,34 @@
}
EXPORT_SYMBOL_GPL(component_master_add_child);
+static int find_components(struct master *master)
+{
+ struct component_match *match = master->match;
+ size_t i;
+ int ret = 0;
+
+ if (!match) {
+ /*
+ * Search the list of components, looking for components that
+ * belong to this master, and attach them to the master.
+ */
+ return master->ops->add_components(master->dev, master);
+ }
+
+ /*
+ * Scan the array of match functions and attach
+ * any components which are found to this master.
+ */
+ for (i = 0; i < match->num; i++) {
+ ret = component_master_add_child(master,
+ match->compare[i].fn,
+ match->compare[i].data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
/* Detach all attached components from this master */
static void master_remove_components(struct master *master)
{
@@ -113,44 +157,44 @@
static int try_to_bring_up_master(struct master *master,
struct component *component)
{
- int ret = 0;
+ int ret;
- if (!master->bound) {
- /*
- * Search the list of components, looking for components that
- * belong to this master, and attach them to the master.
- */
- if (master->ops->add_components(master->dev, master)) {
- /* Failed to find all components */
- master_remove_components(master);
- ret = 0;
- goto out;
- }
+ if (master->bound)
+ return 0;
- if (component && component->master != master) {
- master_remove_components(master);
- ret = 0;
- goto out;
- }
-
- if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* Found all components */
- ret = master->ops->bind(master->dev);
- if (ret < 0) {
- devres_release_group(master->dev, NULL);
- dev_info(master->dev, "master bind failed: %d\n", ret);
- master_remove_components(master);
- goto out;
- }
-
- master->bound = true;
- ret = 1;
+ /*
+ * Search the list of components, looking for components that
+ * belong to this master, and attach them to the master.
+ */
+ if (find_components(master)) {
+ /* Failed to find all components */
+ ret = 0;
+ goto out;
}
+
+ if (component && component->master != master) {
+ ret = 0;
+ goto out;
+ }
+
+ if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Found all components */
+ ret = master->ops->bind(master->dev);
+ if (ret < 0) {
+ devres_release_group(master->dev, NULL);
+ dev_info(master->dev, "master bind failed: %d\n", ret);
+ goto out;
+ }
+
+ master->bound = true;
+ return 1;
+
out:
+ master_remove_components(master);
return ret;
}
@@ -180,18 +224,87 @@
master_remove_components(master);
}
-int component_master_add(struct device *dev,
- const struct component_master_ops *ops)
+static size_t component_match_size(size_t num)
+{
+ return offsetof(struct component_match, compare[num]);
+}
+
+static struct component_match *component_match_realloc(struct device *dev,
+ struct component_match *match, size_t num)
+{
+ struct component_match *new;
+
+ if (match && match->alloc == num)
+ return match;
+
+ new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);
+ if (!new)
+ return ERR_PTR(-ENOMEM);
+
+ if (match) {
+ memcpy(new, match, component_match_size(min(match->num, num)));
+ devm_kfree(dev, match);
+ } else {
+ new->num = 0;
+ }
+
+ new->alloc = num;
+
+ return new;
+}
+
+/*
+ * Add a component to be matched.
+ *
+ * The match array is first created or extended if necessary.
+ */
+void component_match_add(struct device *dev, struct component_match **matchptr,
+ int (*compare)(struct device *, void *), void *compare_data)
+{
+ struct component_match *match = *matchptr;
+
+ if (IS_ERR(match))
+ return;
+
+ if (!match || match->num == match->alloc) {
+ size_t new_size = match ? match->alloc + 16 : 15;
+
+ match = component_match_realloc(dev, match, new_size);
+
+ *matchptr = match;
+
+ if (IS_ERR(match))
+ return;
+ }
+
+ match->compare[match->num].fn = compare;
+ match->compare[match->num].data = compare_data;
+ match->num++;
+}
+EXPORT_SYMBOL(component_match_add);
+
+int component_master_add_with_match(struct device *dev,
+ const struct component_master_ops *ops,
+ struct component_match *match)
{
struct master *master;
int ret;
+ if (ops->add_components && match)
+ return -EINVAL;
+
+ /* Reallocate the match array for its true size */
+ match = component_match_realloc(dev, match, match->num);
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master)
return -ENOMEM;
master->dev = dev;
master->ops = ops;
+ master->match = match;
INIT_LIST_HEAD(&master->components);
/* Add to the list of available masters. */
@@ -209,6 +322,13 @@
return ret < 0 ? ret : 0;
}
+EXPORT_SYMBOL_GPL(component_master_add_with_match);
+
+int component_master_add(struct device *dev,
+ const struct component_master_ops *ops)
+{
+ return component_master_add_with_match(dev, ops, NULL);
+}
EXPORT_SYMBOL_GPL(component_master_add);
void component_master_del(struct device *dev,
diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c
index 6159b77..f2cd6a2d 100644
--- a/drivers/bus/brcmstb_gisb.c
+++ b/drivers/bus/brcmstb_gisb.c
@@ -212,9 +212,9 @@
mutex_init(&gdev->lock);
INIT_LIST_HEAD(&gdev->next);
- gdev->base = devm_request_and_ioremap(&pdev->dev, r);
- if (!gdev->base)
- return -ENOMEM;
+ gdev->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(gdev->base))
+ return PTR_ERR(gdev->base);
err = devm_request_irq(&pdev->dev, timeout_irq,
brcmstb_gisb_timeout_handler, 0, pdev->name,
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 81c34f9..3aedf9e 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1039,11 +1039,9 @@
if (ret)
return ret;
- base = devm_request_and_ioremap(dev->dev, res);
- if (!base) {
- DRM_ERROR("failed to ioremap register\n");
- return -ENOMEM;
- }
+ base = devm_ioremap_resource(dev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);
if (!dcrtc) {
diff --git a/include/linux/component.h b/include/linux/component.h
index 6887018..c00dcc3 100644
--- a/include/linux/component.h
+++ b/include/linux/component.h
@@ -29,4 +29,11 @@
int component_master_add_child(struct master *master,
int (*compare)(struct device *, void *), void *compare_data);
+struct component_match;
+
+int component_master_add_with_match(struct device *,
+ const struct component_master_ops *, struct component_match *);
+void component_match_add(struct device *, struct component_match **,
+ int (*compare)(struct device *, void *), void *compare_data);
+
#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index af424ac..921fa0a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -631,8 +631,6 @@
extern void devm_free_pages(struct device *dev, unsigned long addr);
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
-void __iomem *devm_request_and_ioremap(struct device *dev,
- struct resource *res);
/* allows to add/remove a custom action to devres stack */
int devm_add_action(struct device *dev, void (*action)(void *), void *data);
diff --git a/lib/devres.c b/lib/devres.c
index f562bf6..6a4aee8 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -142,34 +142,6 @@
}
EXPORT_SYMBOL(devm_ioremap_resource);
-/**
- * devm_request_and_ioremap() - Check, request region, and ioremap resource
- * @dev: Generic device to handle the resource for
- * @res: resource to be handled
- *
- * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
- * everything is undone on driver detach. Checks arguments, so you can feed
- * it the result from e.g. platform_get_resource() directly. Returns the
- * remapped pointer or NULL on error. Usage example:
- *
- * res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- * base = devm_request_and_ioremap(&pdev->dev, res);
- * if (!base)
- * return -EADDRNOTAVAIL;
- */
-void __iomem *devm_request_and_ioremap(struct device *dev,
- struct resource *res)
-{
- void __iomem *dest_ptr;
-
- dest_ptr = devm_ioremap_resource(dev, res);
- if (IS_ERR(dest_ptr))
- return NULL;
-
- return dest_ptr;
-}
-EXPORT_SYMBOL(devm_request_and_ioremap);
-
#ifdef CONFIG_HAS_IOPORT_MAP
/*
* Generic iomap devres
diff --git a/scripts/coccinelle/api/devm_ioremap_resource.cocci b/scripts/coccinelle/api/devm_ioremap_resource.cocci
deleted file mode 100644
index 495daa3..0000000
--- a/scripts/coccinelle/api/devm_ioremap_resource.cocci
+++ /dev/null
@@ -1,90 +0,0 @@
-virtual patch
-virtual report
-
-@depends on patch@
-expression base, dev, res;
-@@
-
--base = devm_request_and_ioremap(dev, res);
-+base = devm_ioremap_resource(dev, res);
- ...
- if (
--base == NULL
-+IS_ERR(base)
- || ...) {
-<...
-- return ...;
-+ return PTR_ERR(base);
-...>
- }
-
-@depends on patch@
-expression e, E, ret;
-identifier l;
-@@
-
- e = devm_ioremap_resource(...);
- ...
- if (IS_ERR(e) || ...) {
- ... when any
-- ret = E;
-+ ret = PTR_ERR(e);
- ...
-(
- return ret;
-|
- goto l;
-)
- }
-
-@depends on patch@
-expression e;
-@@
-
- e = devm_ioremap_resource(...);
- ...
- if (IS_ERR(e) || ...) {
- ...
-- \(dev_dbg\|dev_err\|pr_debug\|pr_err\|DRM_ERROR\)(...);
- ...
- }
-
-@depends on patch@
-expression e;
-identifier l;
-@@
-
- e = devm_ioremap_resource(...);
- ...
- if (IS_ERR(e) || ...)
--{
-(
- return ...;
-|
- goto l;
-)
--}
-
-@r depends on report@
-expression e;
-identifier l;
-position p1;
-@@
-
-*e = devm_request_and_ioremap@p1(...);
- ...
- if (e == NULL || ...) {
- ...
-(
- return ...;
-|
- goto l;
-)
- }
-
-@script:python depends on r@
-p1 << r.p1;
-@@
-
-msg = "ERROR: deprecated devm_request_and_ioremap() API used on line %s" % (p1[0].line)
-coccilib.report.print_report(p1[0], msg)