diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2019-08-29 17:17:43 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2019-08-29 17:35:11 +1000 |
commit | 287ae3cd078635df3aa9f620b803fdc39de979da (patch) | |
tree | 276941dad272eaefe7a3ebf998cd8efac688507c | |
parent | 65ba4d54fc7b8076477d8da7acb608a57f57d34d (diff) | |
parent | 6e7e5c7fbc1c84e4ac657e0cb5bf9ca24492cc8f (diff) | |
download | linux-next-287ae3cd078635df3aa9f620b803fdc39de979da.tar.gz |
Merge remote-tracking branch 'driver-core/driver-core-next'
-rw-r--r-- | Documentation/driver-api/device_link.rst | 4 | ||||
-rw-r--r-- | arch/x86/platform/olpc/olpc-xo1-sci.c | 17 | ||||
-rw-r--r-- | drivers/base/core.c | 180 | ||||
-rw-r--r-- | drivers/base/devcoredump.c | 13 | ||||
-rw-r--r-- | drivers/base/platform.c | 65 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 4 | ||||
-rw-r--r-- | drivers/firmware/arm_scpi.c | 5 | ||||
-rw-r--r-- | drivers/hwmon/pwm-fan.c | 2 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-acpi.c | 5 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 47 | ||||
-rw-r--r-- | drivers/uio/uio_fsl_elbc_gpcm.c | 23 | ||||
-rw-r--r-- | drivers/video/fbdev/sm501fb.c | 37 | ||||
-rw-r--r-- | drivers/video/fbdev/w100fb.c | 23 | ||||
-rw-r--r-- | drivers/video/fbdev/wm8505fb.c | 13 | ||||
-rw-r--r-- | fs/kernfs/dir.c | 9 | ||||
-rw-r--r-- | include/linux/device.h | 16 | ||||
-rw-r--r-- | include/linux/platform_device.h | 1 | ||||
-rw-r--r-- | scripts/coccinelle/api/platform_get_irq.cocci | 102 |
18 files changed, 342 insertions, 224 deletions
diff --git a/Documentation/driver-api/device_link.rst b/Documentation/driver-api/device_link.rst index ae1e3d0394b0..1b5020ec6517 100644 --- a/Documentation/driver-api/device_link.rst +++ b/Documentation/driver-api/device_link.rst @@ -78,8 +78,8 @@ typically deleted in its ``->remove`` callback for symmetry. That way, if the driver is compiled as a module, the device link is added on module load and orderly deleted on unload. The same restrictions that apply to device link addition (e.g. exclusion of a parallel suspend/resume transition) apply equally -to deletion. Device links with ``DL_FLAG_STATELESS`` unset (i.e. managed -device links) are deleted automatically by the driver core. +to deletion. Device links managed by the driver core are deleted automatically +by it. Several flags may be specified on device link addition, two of which have already been mentioned above: ``DL_FLAG_STATELESS`` to express that no diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c index 25ce1b3b0732..99a28ce2244c 100644 --- a/arch/x86/platform/olpc/olpc-xo1-sci.c +++ b/arch/x86/platform/olpc/olpc-xo1-sci.c @@ -157,6 +157,12 @@ static ssize_t lid_wake_mode_set(struct device *dev, static DEVICE_ATTR(lid_wake_mode, S_IWUSR | S_IRUGO, lid_wake_mode_show, lid_wake_mode_set); +static struct attribute *lid_attrs[] = { + &dev_attr_lid_wake_mode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(lid); + /* * Process all items in the EC's SCI queue. * @@ -510,17 +516,8 @@ static int setup_lid_switch(struct platform_device *pdev) goto err_register; } - r = device_create_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode); - if (r) { - dev_err(&pdev->dev, "failed to create wake mode attr: %d\n", r); - goto err_create_attr; - } - return 0; -err_create_attr: - input_unregister_device(lid_switch_idev); - lid_switch_idev = NULL; err_register: input_free_device(lid_switch_idev); return r; @@ -528,7 +525,6 @@ err_register: static void free_lid_switch(void) { - device_remove_file(&lid_switch_idev->dev, &dev_attr_lid_wake_mode); input_unregister_device(lid_switch_idev); } @@ -624,6 +620,7 @@ static int xo1_sci_remove(struct platform_device *pdev) static struct platform_driver xo1_sci_driver = { .driver = { .name = "olpc-xo1-sci-acpi", + .dev_groups = lid_groups, }, .probe = xo1_sci_probe, .remove = xo1_sci_remove, diff --git a/drivers/base/core.c b/drivers/base/core.c index 832d4eae501e..2db62d98e395 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -136,6 +136,50 @@ static int device_is_dependent(struct device *dev, void *target) return ret; } +static void device_link_init_status(struct device_link *link, + struct device *consumer, + struct device *supplier) +{ + switch (supplier->links.status) { + case DL_DEV_PROBING: + switch (consumer->links.status) { + case DL_DEV_PROBING: + /* + * A consumer driver can create a link to a supplier + * that has not completed its probing yet as long as it + * knows that the supplier is already functional (for + * example, it has just acquired some resources from the + * supplier). + */ + link->status = DL_STATE_CONSUMER_PROBE; + break; + default: + link->status = DL_STATE_DORMANT; + break; + } + break; + case DL_DEV_DRIVER_BOUND: + switch (consumer->links.status) { + case DL_DEV_PROBING: + link->status = DL_STATE_CONSUMER_PROBE; + break; + case DL_DEV_DRIVER_BOUND: + link->status = DL_STATE_ACTIVE; + break; + default: + link->status = DL_STATE_AVAILABLE; + break; + } + break; + case DL_DEV_UNBINDING: + link->status = DL_STATE_SUPPLIER_UNBIND; + break; + default: + link->status = DL_STATE_DORMANT; + break; + } +} + static int device_reorder_to_tail(struct device *dev, void *not_used) { struct device_link *link; @@ -177,6 +221,13 @@ void device_pm_move_to_tail(struct device *dev) device_links_read_unlock(idx); } +#define DL_MANAGED_LINK_FLAGS (DL_FLAG_AUTOREMOVE_CONSUMER | \ + DL_FLAG_AUTOREMOVE_SUPPLIER | \ + DL_FLAG_AUTOPROBE_CONSUMER) + +#define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) + /** * device_link_add - Create a link between two devices. * @consumer: Consumer end of the link. @@ -191,9 +242,9 @@ void device_pm_move_to_tail(struct device *dev) * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * ignored. * - * If DL_FLAG_STATELESS is set in @flags, the link is not going to be managed by - * the driver core and, in particular, the caller of this function is expected - * to drop the reference to the link acquired by it directly. + * If DL_FLAG_STATELESS is set in @flags, the caller of this function is + * expected to release the link returned by it directly with the help of either + * device_link_del() or device_link_remove(). * * If that flag is not set, however, the caller of this function is handing the * management of the link over to the driver core entirely and its return value @@ -213,9 +264,16 @@ void device_pm_move_to_tail(struct device *dev) * be used to request the driver core to automaticall probe for a consmer * driver after successfully binding a driver to the supplier device. * - * The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER - * or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and - * will cause NULL to be returned upfront. + * The combination of DL_FLAG_STATELESS and one of DL_FLAG_AUTOREMOVE_CONSUMER, + * DL_FLAG_AUTOREMOVE_SUPPLIER, or DL_FLAG_AUTOPROBE_CONSUMER set in @flags at + * the same time is invalid and will cause NULL to be returned upfront. + * However, if a device link between the given @consumer and @supplier pair + * exists already when this function is called for them, the existing link will + * be returned regardless of its current type and status (the link's flags may + * be modified then). The caller of this function is then expected to treat + * the link as though it has just been created, so (in particular) if + * DL_FLAG_STATELESS was passed in @flags, the link needs to be released + * explicitly when not needed any more (as stated above). * * A side effect of the link creation is re-ordering of dpm_list and the * devices_kset list by moving the consumer device and all devices depending @@ -231,11 +289,8 @@ struct device_link *device_link_add(struct device *consumer, { struct device_link *link; - if (!consumer || !supplier || - (flags & DL_FLAG_STATELESS && - flags & (DL_FLAG_AUTOREMOVE_CONSUMER | - DL_FLAG_AUTOREMOVE_SUPPLIER | - DL_FLAG_AUTOPROBE_CONSUMER)) || + if (!consumer || !supplier || flags & ~DL_ADD_VALID_FLAGS || + (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) @@ -248,6 +303,9 @@ struct device_link *device_link_add(struct device *consumer, } } + if (!(flags & DL_FLAG_STATELESS)) + flags |= DL_FLAG_MANAGED; + device_links_write_lock(); device_pm_lock(); @@ -274,15 +332,6 @@ struct device_link *device_link_add(struct device *consumer, if (link->consumer != consumer) continue; - /* - * Don't return a stateless link if the caller wants a stateful - * one and vice versa. - */ - if (WARN_ON((flags & DL_FLAG_STATELESS) != (link->flags & DL_FLAG_STATELESS))) { - link = NULL; - goto out; - } - if (flags & DL_FLAG_PM_RUNTIME) { if (!(link->flags & DL_FLAG_PM_RUNTIME)) { pm_runtime_new_link(consumer); @@ -293,6 +342,7 @@ struct device_link *device_link_add(struct device *consumer, } if (flags & DL_FLAG_STATELESS) { + link->flags |= DL_FLAG_STATELESS; kref_get(&link->kref); goto out; } @@ -311,6 +361,11 @@ struct device_link *device_link_add(struct device *consumer, link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER); } + if (!(link->flags & DL_FLAG_MANAGED)) { + kref_get(&link->kref); + link->flags |= DL_FLAG_MANAGED; + device_link_init_status(link, consumer, supplier); + } goto out; } @@ -337,48 +392,10 @@ struct device_link *device_link_add(struct device *consumer, kref_init(&link->kref); /* Determine the initial link state. */ - if (flags & DL_FLAG_STATELESS) { + if (flags & DL_FLAG_STATELESS) link->status = DL_STATE_NONE; - } else { - switch (supplier->links.status) { - case DL_DEV_PROBING: - switch (consumer->links.status) { - case DL_DEV_PROBING: - /* - * A consumer driver can create a link to a - * supplier that has not completed its probing - * yet as long as it knows that the supplier is - * already functional (for example, it has just - * acquired some resources from the supplier). - */ - link->status = DL_STATE_CONSUMER_PROBE; - break; - default: - link->status = DL_STATE_DORMANT; - break; - } - break; - case DL_DEV_DRIVER_BOUND: - switch (consumer->links.status) { - case DL_DEV_PROBING: - link->status = DL_STATE_CONSUMER_PROBE; - break; - case DL_DEV_DRIVER_BOUND: - link->status = DL_STATE_ACTIVE; - break; - default: - link->status = DL_STATE_AVAILABLE; - break; - } - break; - case DL_DEV_UNBINDING: - link->status = DL_STATE_SUPPLIER_UNBIND; - break; - default: - link->status = DL_STATE_DORMANT; - break; - } - } + else + device_link_init_status(link, consumer, supplier); /* * Some callers expect the link creation during consumer driver probe to @@ -540,7 +557,7 @@ static void device_links_missing_supplier(struct device *dev) * mark the link as "consumer probe in progress" to make the supplier removal * wait for us to complete (or bad things may happen). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ int device_links_check_suppliers(struct device *dev) { @@ -550,7 +567,7 @@ int device_links_check_suppliers(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->status != DL_STATE_AVAILABLE) { @@ -575,7 +592,7 @@ int device_links_check_suppliers(struct device *dev) * * Also change the status of @dev's links to suppliers to "active". * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_driver_bound(struct device *dev) { @@ -584,7 +601,7 @@ void device_links_driver_bound(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; /* @@ -605,7 +622,7 @@ void device_links_driver_bound(struct device *dev) } list_for_each_entry(link, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; WARN_ON(link->status != DL_STATE_CONSUMER_PROBE); @@ -617,6 +634,13 @@ void device_links_driver_bound(struct device *dev) device_links_write_unlock(); } +static void device_link_drop_managed(struct device_link *link) +{ + link->flags &= ~DL_FLAG_MANAGED; + WRITE_ONCE(link->status, DL_STATE_NONE); + kref_put(&link->kref, __device_link_del); +} + /** * __device_links_no_driver - Update links of a device without a driver. * @dev: Device without a drvier. @@ -627,18 +651,18 @@ void device_links_driver_bound(struct device *dev) * unless they already are in the "supplier unbind in progress" state in which * case they need not be updated. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ static void __device_links_no_driver(struct device *dev) { struct device_link *link, *ln; list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) - __device_link_del(&link->kref); + device_link_drop_managed(link); else if (link->status == DL_STATE_CONSUMER_PROBE || link->status == DL_STATE_ACTIVE) WRITE_ONCE(link->status, DL_STATE_AVAILABLE); @@ -655,7 +679,7 @@ static void __device_links_no_driver(struct device *dev) * %__device_links_no_driver() to update links to suppliers for it as * appropriate. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_no_driver(struct device *dev) { @@ -664,7 +688,7 @@ void device_links_no_driver(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; /* @@ -692,7 +716,7 @@ void device_links_no_driver(struct device *dev) * invoke %__device_links_no_driver() to update links to suppliers for it as * appropriate. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_driver_cleanup(struct device *dev) { @@ -701,7 +725,7 @@ void device_links_driver_cleanup(struct device *dev) device_links_write_lock(); list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); @@ -714,7 +738,7 @@ void device_links_driver_cleanup(struct device *dev) */ if (link->status == DL_STATE_SUPPLIER_UNBIND && link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) - __device_link_del(&link->kref); + device_link_drop_managed(link); WRITE_ONCE(link->status, DL_STATE_DORMANT); } @@ -736,7 +760,7 @@ void device_links_driver_cleanup(struct device *dev) * * Return 'false' if there are no probing or active consumers. * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ bool device_links_busy(struct device *dev) { @@ -746,7 +770,7 @@ bool device_links_busy(struct device *dev) device_links_write_lock(); list_for_each_entry(link, &dev->links.consumers, s_node) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; if (link->status == DL_STATE_CONSUMER_PROBE @@ -776,7 +800,7 @@ bool device_links_busy(struct device *dev) * driver to unbind and start over (the consumer will not re-probe as we have * changed the state of the link already). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links without the DL_FLAG_MANAGED flag set are ignored. */ void device_links_unbind_consumers(struct device *dev) { @@ -788,7 +812,7 @@ void device_links_unbind_consumers(struct device *dev) list_for_each_entry(link, &dev->links.consumers, s_node) { enum device_link_state status; - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; status = link->status; diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c index f1a3353f3494..e42d0b514384 100644 --- a/drivers/base/devcoredump.c +++ b/drivers/base/devcoredump.c @@ -164,16 +164,7 @@ static struct class devcd_class = { static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, void *data, size_t datalen) { - if (offset > datalen) - return -EINVAL; - - if (offset + count > datalen) - count = datalen - offset; - - if (count) - memcpy(buffer, ((u8 *)data) + offset, count); - - return count; + return memory_read_from_buffer(buffer, count, &offset, data, datalen); } static void devcd_freev(void *data) @@ -323,7 +314,7 @@ void dev_coredumpm(struct device *dev, struct module *owner, EXPORT_SYMBOL_GPL(dev_coredumpm); /** - * dev_coredumpmsg - create device coredump that uses scatterlist as data + * dev_coredumpsg - create device coredump that uses scatterlist as data * parameter * @dev: the struct device for the crashed device * @table: the dump data diff --git a/drivers/base/platform.c b/drivers/base/platform.c index eb018378d60a..11c6e56ccc22 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -99,12 +99,7 @@ void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); #endif /* CONFIG_HAS_IOMEM */ -/** - * platform_get_irq - get an IRQ for a device - * @dev: platform device - * @num: IRQ number index - */ -int platform_get_irq(struct platform_device *dev, unsigned int num) +static int __platform_get_irq(struct platform_device *dev, unsigned int num) { #ifdef CONFIG_SPARC /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ @@ -168,9 +163,59 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) return -ENXIO; #endif } + +/** + * platform_get_irq - get an IRQ for a device + * @dev: platform device + * @num: IRQ number index + * + * Gets an IRQ for a platform device and prints an error message if finding the + * IRQ fails. Device drivers should check the return value for errors so as to + * not pass a negative integer value to the request_irq() APIs. + * + * Example: + * int irq = platform_get_irq(pdev, 0); + * if (irq < 0) + * return irq; + * + * Return: IRQ number on success, negative error number on failure. + */ +int platform_get_irq(struct platform_device *dev, unsigned int num) +{ + int ret; + + ret = __platform_get_irq(dev, num); + if (ret < 0 && ret != -EPROBE_DEFER) + dev_err(&dev->dev, "IRQ index %u not found\n", num); + + return ret; +} EXPORT_SYMBOL_GPL(platform_get_irq); /** + * platform_get_irq_optional - get an optional IRQ for a device + * @dev: platform device + * @num: IRQ number index + * + * Gets an IRQ for a platform device. Device drivers should check the return + * value for errors so as to not pass a negative integer value to the + * request_irq() APIs. This is the same as platform_get_irq(), except that it + * does not print an error message if an IRQ can not be obtained. + * + * Example: + * int irq = platform_get_irq_optional(pdev, 0); + * if (irq < 0) + * return irq; + * + * Return: IRQ number on success, negative error number on failure. + */ +int platform_get_irq_optional(struct platform_device *dev, unsigned int num) +{ + return __platform_get_irq(dev, num); +} +EXPORT_SYMBOL_GPL(platform_get_irq_optional); + +/** * platform_irq_count - Count the number of IRQs a platform device uses * @dev: platform device * @@ -180,7 +225,7 @@ int platform_irq_count(struct platform_device *dev) { int ret, nr = 0; - while ((ret = platform_get_irq(dev, nr)) >= 0) + while ((ret = __platform_get_irq(dev, nr)) >= 0) nr++; if (ret == -EPROBE_DEFER) @@ -233,7 +278,11 @@ int platform_get_irq_byname(struct platform_device *dev, const char *name) } r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); - return r ? r->start : -ENXIO; + if (r) + return r->start; + + dev_err(&dev->dev, "IRQ %s not found\n", name); + return -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq_byname); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 50def99df970..48616f358854 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1626,7 +1626,7 @@ void pm_runtime_remove(struct device *dev) * runtime PM references to the device, drop the usage counter of the device * (as many times as needed). * - * Links with the DL_FLAG_STATELESS flag set are ignored. + * Links with the DL_FLAG_MANAGED flag unset are ignored. * * Since the device is guaranteed to be runtime-active at the point this is * called, nothing else needs to be done here. @@ -1644,7 +1644,7 @@ void pm_runtime_clean_up_links(struct device *dev) list_for_each_entry_rcu(link, &dev->links.consumers, s_node, device_links_read_lock_held()) { - if (link->flags & DL_FLAG_STATELESS) + if (!(link->flags & DL_FLAG_MANAGED)) continue; while (refcount_dec_not_one(&link->rpm_active)) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 725164b83242..a80c331c3a6e 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -1011,10 +1011,6 @@ static int scpi_probe(struct platform_device *pdev) scpi_info->firmware_version)); scpi_info->scpi_ops = &scpi_ops; - ret = devm_device_add_groups(dev, versions_groups); - if (ret) - dev_err(dev, "unable to create sysfs version group\n"); - return devm_of_platform_populate(dev); } @@ -1030,6 +1026,7 @@ static struct platform_driver scpi_driver = { .driver = { .name = "scpi_protocol", .of_match_table = scpi_of_match, + .dev_groups = versions_groups, }, .probe = scpi_probe, .remove = scpi_remove, diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index 54c0ff00d67f..42ffd2e5182d 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -304,7 +304,7 @@ static int pwm_fan_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); - ctx->irq = platform_get_irq(pdev, 0); + ctx->irq = platform_get_irq_optional(pdev, 0); if (ctx->irq == -EPROBE_DEFER) return ctx->irq; diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index bc80aafb521f..f60f7a95d48e 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -357,7 +357,10 @@ static int i2c_acpi_find_match_adapter(struct device *dev, const void *data) struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) { - struct device *dev = bus_find_device_by_acpi_dev(&i2c_bus_type, handle); + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, handle, + i2c_acpi_find_match_adapter); return dev ? i2c_verify_adapter(dev) : NULL; } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 2521e45280b8..6bcbbb375401 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -502,6 +502,17 @@ static DEVICE_ATTR_RO(dock); static DEVICE_ATTR_RO(tablet); static DEVICE_ATTR_RW(postcode); +static struct attribute *hp_wmi_attrs[] = { + &dev_attr_display.attr, + &dev_attr_hddtemp.attr, + &dev_attr_als.attr, + &dev_attr_dock.attr, + &dev_attr_tablet.attr, + &dev_attr_postcode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(hp_wmi); + static void hp_wmi_notify(u32 value, void *context) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -678,16 +689,6 @@ static void hp_wmi_input_destroy(void) input_unregister_device(hp_wmi_input_dev); } -static void cleanup_sysfs(struct platform_device *device) -{ - device_remove_file(&device->dev, &dev_attr_display); - device_remove_file(&device->dev, &dev_attr_hddtemp); - device_remove_file(&device->dev, &dev_attr_als); - device_remove_file(&device->dev, &dev_attr_dock); - device_remove_file(&device->dev, &dev_attr_tablet); - device_remove_file(&device->dev, &dev_attr_postcode); -} - static int __init hp_wmi_rfkill_setup(struct platform_device *device) { int err, wireless; @@ -858,8 +859,6 @@ fail: static int __init hp_wmi_bios_setup(struct platform_device *device) { - int err; - /* clear detected rfkill devices */ wifi_rfkill = NULL; bluetooth_rfkill = NULL; @@ -869,35 +868,12 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) if (hp_wmi_rfkill_setup(device)) hp_wmi_rfkill2_setup(device); - err = device_create_file(&device->dev, &dev_attr_display); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_hddtemp); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_als); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_dock); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_tablet); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_postcode); - if (err) - goto add_sysfs_error; return 0; - -add_sysfs_error: - cleanup_sysfs(device); - return err; } static int __exit hp_wmi_bios_remove(struct platform_device *device) { int i; - cleanup_sysfs(device); for (i = 0; i < rfkill2_count; i++) { rfkill_unregister(rfkill2[i].rfkill); @@ -966,6 +942,7 @@ static struct platform_driver hp_wmi_driver = { .driver = { .name = "hp-wmi", .pm = &hp_wmi_pm_ops, + .dev_groups = hp_wmi_groups, }, .remove = __exit_p(hp_wmi_bios_remove), }; diff --git a/drivers/uio/uio_fsl_elbc_gpcm.c b/drivers/uio/uio_fsl_elbc_gpcm.c index 450e2f5c9b43..be8a6905f507 100644 --- a/drivers/uio/uio_fsl_elbc_gpcm.c +++ b/drivers/uio/uio_fsl_elbc_gpcm.c @@ -71,6 +71,13 @@ static ssize_t reg_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(reg_br, 0664, reg_show, reg_store); static DEVICE_ATTR(reg_or, 0664, reg_show, reg_store); +static struct attribute *uio_fsl_elbc_gpcm_attrs[] = { + &dev_attr_reg_br.attr, + &dev_attr_reg_or.attr, + NULL, +}; +ATTRIBUTE_GROUPS(uio_fsl_elbc_gpcm); + static ssize_t reg_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -411,25 +418,12 @@ static int uio_fsl_elbc_gpcm_probe(struct platform_device *pdev) /* store private data */ platform_set_drvdata(pdev, info); - /* create sysfs files */ - ret = device_create_file(priv->dev, &dev_attr_reg_br); - if (ret) - goto out_err3; - ret = device_create_file(priv->dev, &dev_attr_reg_or); - if (ret) - goto out_err4; - dev_info(priv->dev, "eLBC/GPCM device (%s) at 0x%llx, bank %d, irq=%d\n", priv->name, (unsigned long long)res.start, priv->bank, irq != NO_IRQ ? irq : -1); return 0; -out_err4: - device_remove_file(priv->dev, &dev_attr_reg_br); -out_err3: - platform_set_drvdata(pdev, NULL); - uio_unregister_device(info); out_err2: if (priv->shutdown) priv->shutdown(info, true); @@ -448,8 +442,6 @@ static int uio_fsl_elbc_gpcm_remove(struct platform_device *pdev) struct uio_info *info = platform_get_drvdata(pdev); struct fsl_elbc_gpcm *priv = info->priv; - device_remove_file(priv->dev, &dev_attr_reg_or); - device_remove_file(priv->dev, &dev_attr_reg_br); platform_set_drvdata(pdev, NULL); uio_unregister_device(info); if (priv->shutdown) @@ -474,6 +466,7 @@ static struct platform_driver uio_fsl_elbc_gpcm_driver = { .driver = { .name = "fsl,elbc-gpcm-uio", .of_match_table = uio_fsl_elbc_gpcm_match, + .dev_groups = uio_fsl_elbc_gpcm_groups, }, .probe = uio_fsl_elbc_gpcm_probe, .remove = uio_fsl_elbc_gpcm_remove, diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index 6edb4492e675..3dd1b1d76e98 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1271,6 +1271,14 @@ static ssize_t sm501fb_debug_show_pnl(struct device *dev, static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); +static struct attribute *sm501fb_attrs[] = { + &dev_attr_crt_src.attr, + &dev_attr_fbregs_pnl.attr, + &dev_attr_fbregs_crt.attr, + NULL, +}; +ATTRIBUTE_GROUPS(sm501fb); + /* acceleration operations */ static int sm501fb_sync(struct fb_info *info) { @@ -2011,33 +2019,9 @@ static int sm501fb_probe(struct platform_device *pdev) goto err_started_crt; } - /* create device files */ - - ret = device_create_file(dev, &dev_attr_crt_src); - if (ret) - goto err_started_panel; - - ret = device_create_file(dev, &dev_attr_fbregs_pnl); - if (ret) - goto err_attached_crtsrc_file; - - ret = device_create_file(dev, &dev_attr_fbregs_crt); - if (ret) - goto err_attached_pnlregs_file; - /* we registered, return ok */ return 0; -err_attached_pnlregs_file: - device_remove_file(dev, &dev_attr_fbregs_pnl); - -err_attached_crtsrc_file: - device_remove_file(dev, &dev_attr_crt_src); - -err_started_panel: - unregister_framebuffer(info->fb[HEAD_PANEL]); - sm501_free_init_fb(info, HEAD_PANEL); - err_started_crt: unregister_framebuffer(info->fb[HEAD_CRT]); sm501_free_init_fb(info, HEAD_CRT); @@ -2067,10 +2051,6 @@ static int sm501fb_remove(struct platform_device *pdev) struct fb_info *fbinfo_crt = info->fb[0]; struct fb_info *fbinfo_pnl = info->fb[1]; - device_remove_file(&pdev->dev, &dev_attr_fbregs_crt); - device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); - device_remove_file(&pdev->dev, &dev_attr_crt_src); - sm501_free_init_fb(info, HEAD_CRT); sm501_free_init_fb(info, HEAD_PANEL); @@ -2234,6 +2214,7 @@ static struct platform_driver sm501fb_driver = { .resume = sm501fb_resume, .driver = { .name = "sm501-fb", + .dev_groups = sm501fb_groups, }, }; diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c index 597ffaa13cd2..3be07807edcd 100644 --- a/drivers/video/fbdev/w100fb.c +++ b/drivers/video/fbdev/w100fb.c @@ -164,6 +164,15 @@ static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *att static DEVICE_ATTR_RW(fastpllclk); +static struct attribute *w100fb_attrs[] = { + &dev_attr_fastpllclk.attr, + &dev_attr_reg_read.attr, + &dev_attr_reg_write.attr, + &dev_attr_flip.attr, + NULL, +}; +ATTRIBUTE_GROUPS(w100fb); + /* * Some touchscreens need hsync information from the video driver to * function correctly. We export it here. @@ -752,14 +761,6 @@ int w100fb_probe(struct platform_device *pdev) goto out; } - err = device_create_file(&pdev->dev, &dev_attr_fastpllclk); - err |= device_create_file(&pdev->dev, &dev_attr_reg_read); - err |= device_create_file(&pdev->dev, &dev_attr_reg_write); - err |= device_create_file(&pdev->dev, &dev_attr_flip); - - if (err != 0) - fb_warn(info, "failed to register attributes (%d)\n", err); - fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; out: @@ -784,11 +785,6 @@ static int w100fb_remove(struct platform_device *pdev) struct fb_info *info = platform_get_drvdata(pdev); struct w100fb_par *par=info->par; - device_remove_file(&pdev->dev, &dev_attr_fastpllclk); - device_remove_file(&pdev->dev, &dev_attr_reg_read); - device_remove_file(&pdev->dev, &dev_attr_reg_write); - device_remove_file(&pdev->dev, &dev_attr_flip); - unregister_framebuffer(info); vfree(par->saved_intmem); @@ -1625,6 +1621,7 @@ static struct platform_driver w100fb_driver = { .resume = w100fb_resume, .driver = { .name = "w100fb", + .dev_groups = w100fb_groups, }, }; diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c index ff752635a31c..17c780315ca5 100644 --- a/drivers/video/fbdev/wm8505fb.c +++ b/drivers/video/fbdev/wm8505fb.c @@ -176,6 +176,12 @@ static ssize_t contrast_store(struct device *dev, static DEVICE_ATTR_RW(contrast); +static struct attribute *wm8505fb_attrs[] = { + &dev_attr_contrast.attr, + NULL, +}; +ATTRIBUTE_GROUPS(wm8505fb); + static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) { chan &= 0xffff; @@ -361,10 +367,6 @@ static int wm8505fb_probe(struct platform_device *pdev) return ret; } - ret = device_create_file(&pdev->dev, &dev_attr_contrast); - if (ret < 0) - fb_warn(&fbi->fb, "failed to register attributes (%d)\n", ret); - fb_info(&fbi->fb, "%s frame buffer at 0x%lx-0x%lx\n", fbi->fb.fix.id, fbi->fb.fix.smem_start, fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1); @@ -376,8 +378,6 @@ static int wm8505fb_remove(struct platform_device *pdev) { struct wm8505fb_info *fbi = platform_get_drvdata(pdev); - device_remove_file(&pdev->dev, &dev_attr_contrast); - unregister_framebuffer(&fbi->fb); writel(0, fbi->regbase); @@ -399,6 +399,7 @@ static struct platform_driver wm8505fb_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = wmt_dt_ids, + .dev_groups = wm8505fb_groups, }, }; diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index a387534c9577..6ebae6bbe6a5 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -137,6 +137,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, if (kn_from == kn_to) return strlcpy(buf, "/", buflen); + if (!buf) + return -EINVAL; + common = kernfs_common_ancestor(kn_from, kn_to); if (WARN_ON(!common)) return -EINVAL; @@ -144,8 +147,7 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, depth_to = kernfs_depth(common, kn_to); depth_from = kernfs_depth(common, kn_from); - if (buf) - buf[0] = '\0'; + buf[0] = '\0'; for (i = 0; i < depth_from; i++) len += strlcpy(buf + len, parent_str, @@ -430,7 +432,6 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) */ void kernfs_put_active(struct kernfs_node *kn) { - struct kernfs_root *root = kernfs_root(kn); int v; if (unlikely(!kn)) @@ -442,7 +443,7 @@ void kernfs_put_active(struct kernfs_node *kn) if (likely(v != KN_DEACTIVATED_BIAS)) return; - wake_up_all(&root->deactivate_waitq); + wake_up_all(&kernfs_root(kn)->deactivate_waitq); } /** diff --git a/include/linux/device.h b/include/linux/device.h index 49efd209c6bb..ec598ede9455 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -229,6 +229,8 @@ static inline struct device *bus_find_device_by_devt(struct bus_type *bus, /** * bus_find_next_device - Find the next device after a given device in a * given bus. + * @bus: bus type + * @cur: device to begin the search with. */ static inline struct device * bus_find_next_device(struct bus_type *bus,struct device *cur) @@ -432,7 +434,7 @@ struct device *driver_find_device(struct device_driver *drv, /** * driver_find_device_by_name - device iterator for locating a particular device * of a specific name. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @name: name of the device to match */ static inline struct device *driver_find_device_by_name(struct device_driver *drv, @@ -444,7 +446,7 @@ static inline struct device *driver_find_device_by_name(struct device_driver *dr /** * driver_find_device_by_of_node- device iterator for locating a particular device * by of_node pointer. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @np: of_node pointer to match. */ static inline struct device * @@ -457,7 +459,7 @@ driver_find_device_by_of_node(struct device_driver *drv, /** * driver_find_device_by_fwnode- device iterator for locating a particular device * by fwnode pointer. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @fwnode: fwnode pointer to match. */ static inline struct device * @@ -470,7 +472,7 @@ driver_find_device_by_fwnode(struct device_driver *drv, /** * driver_find_device_by_devt- device iterator for locating a particular device * by devt. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @devt: devt pointer to match. */ static inline struct device *driver_find_device_by_devt(struct device_driver *drv, @@ -489,7 +491,7 @@ static inline struct device *driver_find_next_device(struct device_driver *drv, /** * driver_find_device_by_acpi_dev : device iterator for locating a particular * device matching the ACPI_COMPANION device. - * @driver: the driver we're iterating + * @drv: the driver we're iterating * @adev: ACPI_COMPANION device to match. */ static inline struct device * @@ -1067,12 +1069,13 @@ enum device_link_state { /* * Device link flags. * - * STATELESS: The core won't track the presence of supplier/consumer drivers. + * STATELESS: The core will not remove this link automatically. * AUTOREMOVE_CONSUMER: Remove the link automatically on consumer driver unbind. * PM_RUNTIME: If set, the runtime PM framework will use this link. * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. + * MANAGED: The core tracks presence of supplier/consumer drivers (internal). */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) @@ -1080,6 +1083,7 @@ enum device_link_state { #define DL_FLAG_RPM_ACTIVE BIT(3) #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) +#define DL_FLAG_MANAGED BIT(6) /** * struct device_link - Device link representation. diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 37e15a935a42..35bc4355a9df 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -58,6 +58,7 @@ extern void __iomem * devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index); extern int platform_get_irq(struct platform_device *, unsigned int); +extern int platform_get_irq_optional(struct platform_device *, unsigned int); extern int platform_irq_count(struct platform_device *); extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, diff --git a/scripts/coccinelle/api/platform_get_irq.cocci b/scripts/coccinelle/api/platform_get_irq.cocci new file mode 100644 index 000000000000..f6e1afc08c0b --- /dev/null +++ b/scripts/coccinelle/api/platform_get_irq.cocci @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/// Remove dev_err() messages after platform_get_irq*() failures +// +// Confidence: Medium +// Options: --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context@ +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +if (ret != -EPROBE_DEFER) +{ ... +*dev_err(...); +... } +| +... +*dev_err(...); +) +... +} + +@depends on patch@ +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +-if (ret != -EPROBE_DEFER) +-{ ... +-dev_err(...); +-... } +| +... +-dev_err(...); +) +... +} + +@r depends on org || report@ +position p1; +expression ret; +struct platform_device *E; +@@ + +ret = +( +platform_get_irq +| +platform_get_irq_byname +)(E, ...); + +if ( ret \( < \| <= \) 0 ) +{ +( +if (ret != -EPROBE_DEFER) +{ ... +dev_err@p1(...); +... } +| +... +dev_err@p1(...); +) +... +} + +@script:python depends on org@ +p1 << r.p1; +@@ + +cocci.print_main(p1) + +@script:python depends on report@ +p1 << r.p1; +@@ + +msg = "line %s is redundant because platform_get_irq() already prints an error" % (p1[0].line) +coccilib.report.print_report(p1[0],msg) |