diff options
-rw-r--r-- | Documentation/driver-model/devres.txt | 1 | ||||
-rw-r--r-- | drivers/base/component.c | 190 | ||||
-rw-r--r-- | drivers/bus/brcmstb_gisb.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 8 | ||||
-rw-r--r-- | include/linux/component.h | 7 | ||||
-rw-r--r-- | include/linux/device.h | 2 | ||||
-rw-r--r-- | lib/devres.c | 28 | ||||
-rw-r--r-- | scripts/coccinelle/api/devm_ioremap_resource.cocci | 90 |
8 files changed, 168 insertions, 164 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 1525e30483fd..de6bc8c325e9 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -278,7 +278,6 @@ IOMAP 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 c4778995cd72..b4236daed4fa 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 @@ struct master { const struct component_master_ops *ops; struct device *dev; + struct component_match *match; }; struct component { @@ -69,6 +79,11 @@ static void component_detach_master(struct master *master, struct component *c) 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 component_master_add_child(struct master *master, 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 @@ int component_master_add_child(struct master *master, } 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 void master_remove_components(struct master *master) 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; - } + /* + * 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 (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { - ret = -ENOMEM; - goto out; - } + if (component && component->master != master) { + ret = 0; + 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; - } + if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out; + } - master->bound = true; - ret = 1; + /* 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 @@ static void take_down_master(struct master *master) 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 @@ int component_master_add(struct device *dev, 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 6159b7752a64..f2cd6a2d40b4 100644 --- a/drivers/bus/brcmstb_gisb.c +++ b/drivers/bus/brcmstb_gisb.c @@ -212,9 +212,9 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev) 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 81c34f949dfc..3aedf9e993e6 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1039,11 +1039,9 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num, 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 68870182ca1e..c00dcc302611 100644 --- a/include/linux/component.h +++ b/include/linux/component.h @@ -29,4 +29,11 @@ void component_master_del(struct device *, 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 af424acd393d..921fa0a74df6 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -631,8 +631,6 @@ extern unsigned long devm_get_free_pages(struct device *dev, 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 f562bf6ff71d..6a4aee8a3a7e 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -142,34 +142,6 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) } 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 495daa3dbf77..000000000000 --- 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) |