From 507fd01d5333338753a1cc26322dfc9f856c109f Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 3 Oct 2019 11:29:12 +0200 Subject: drivers: move the early platform device support to arch/sh SuperH is the only user of the current implementation of early platform device support. We want to introduce a more robust approach to early probing. As the first step - move all the current early platform code to arch/sh. In order not to export internal drivers/base functions to arch code for this temporary solution - copy the two needed routines for driver matching from drivers/base/platform.c to arch/sh/drivers/platform_early.c. Also: call early_platform_cleanup() from subsys_initcall() so that it's called after all early devices are probed. Signed-off-by: Bartosz Golaszewski Cc: Rich Felker Link: https://lore.kernel.org/r/20191003092913.10731-2-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 288 ------------------------------------------------ 1 file changed, 288 deletions(-) (limited to 'drivers/base/platform.c') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b6c6c7d97d5b..be1e67ee3af6 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1264,8 +1264,6 @@ int __init platform_bus_init(void) { int error; - early_platform_cleanup(); - error = device_register(&platform_bus); if (error) { put_device(&platform_bus); @@ -1277,289 +1275,3 @@ int __init platform_bus_init(void) of_platform_register_reconfig_notifier(); return error; } - -static __initdata LIST_HEAD(early_platform_driver_list); -static __initdata LIST_HEAD(early_platform_device_list); - -/** - * early_platform_driver_register - register early platform driver - * @epdrv: early_platform driver structure - * @buf: string passed from early_param() - * - * Helper function for early_platform_init() / early_platform_init_buffer() - */ -int __init early_platform_driver_register(struct early_platform_driver *epdrv, - char *buf) -{ - char *tmp; - int n; - - /* Simply add the driver to the end of the global list. - * Drivers will by default be put on the list in compiled-in order. - */ - if (!epdrv->list.next) { - INIT_LIST_HEAD(&epdrv->list); - list_add_tail(&epdrv->list, &early_platform_driver_list); - } - - /* If the user has specified device then make sure the driver - * gets prioritized. The driver of the last device specified on - * command line will be put first on the list. - */ - n = strlen(epdrv->pdrv->driver.name); - if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { - list_move(&epdrv->list, &early_platform_driver_list); - - /* Allow passing parameters after device name */ - if (buf[n] == '\0' || buf[n] == ',') - epdrv->requested_id = -1; - else { - epdrv->requested_id = simple_strtoul(&buf[n + 1], - &tmp, 10); - - if (buf[n] != '.' || (tmp == &buf[n + 1])) { - epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; - n = 0; - } else - n += strcspn(&buf[n + 1], ",") + 1; - } - - if (buf[n] == ',') - n++; - - if (epdrv->bufsize) { - memcpy(epdrv->buffer, &buf[n], - min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1)); - epdrv->buffer[epdrv->bufsize - 1] = '\0'; - } - } - - return 0; -} - -/** - * early_platform_add_devices - adds a number of early platform devices - * @devs: array of early platform devices to add - * @num: number of early platform devices in array - * - * Used by early architecture code to register early platform devices and - * their platform data. - */ -void __init early_platform_add_devices(struct platform_device **devs, int num) -{ - struct device *dev; - int i; - - /* simply add the devices to list */ - for (i = 0; i < num; i++) { - dev = &devs[i]->dev; - - if (!dev->devres_head.next) { - pm_runtime_early_init(dev); - INIT_LIST_HEAD(&dev->devres_head); - list_add_tail(&dev->devres_head, - &early_platform_device_list); - } - } -} - -/** - * early_platform_driver_register_all - register early platform drivers - * @class_str: string to identify early platform driver class - * - * Used by architecture code to register all early platform drivers - * for a certain class. If omitted then only early platform drivers - * with matching kernel command line class parameters will be registered. - */ -void __init early_platform_driver_register_all(char *class_str) -{ - /* The "class_str" parameter may or may not be present on the kernel - * command line. If it is present then there may be more than one - * matching parameter. - * - * Since we register our early platform drivers using early_param() - * we need to make sure that they also get registered in the case - * when the parameter is missing from the kernel command line. - * - * We use parse_early_options() to make sure the early_param() gets - * called at least once. The early_param() may be called more than - * once since the name of the preferred device may be specified on - * the kernel command line. early_platform_driver_register() handles - * this case for us. - */ - parse_early_options(class_str); -} - -/** - * early_platform_match - find early platform device matching driver - * @epdrv: early platform driver structure - * @id: id to match against - */ -static struct platform_device * __init -early_platform_match(struct early_platform_driver *epdrv, int id) -{ - struct platform_device *pd; - - list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) - if (platform_match(&pd->dev, &epdrv->pdrv->driver)) - if (pd->id == id) - return pd; - - return NULL; -} - -/** - * early_platform_left - check if early platform driver has matching devices - * @epdrv: early platform driver structure - * @id: return true if id or above exists - */ -static int __init early_platform_left(struct early_platform_driver *epdrv, - int id) -{ - struct platform_device *pd; - - list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) - if (platform_match(&pd->dev, &epdrv->pdrv->driver)) - if (pd->id >= id) - return 1; - - return 0; -} - -/** - * early_platform_driver_probe_id - probe drivers matching class_str and id - * @class_str: string to identify early platform driver class - * @id: id to match against - * @nr_probe: number of platform devices to successfully probe before exiting - */ -static int __init early_platform_driver_probe_id(char *class_str, - int id, - int nr_probe) -{ - struct early_platform_driver *epdrv; - struct platform_device *match; - int match_id; - int n = 0; - int left = 0; - - list_for_each_entry(epdrv, &early_platform_driver_list, list) { - /* only use drivers matching our class_str */ - if (strcmp(class_str, epdrv->class_str)) - continue; - - if (id == -2) { - match_id = epdrv->requested_id; - left = 1; - - } else { - match_id = id; - left += early_platform_left(epdrv, id); - - /* skip requested id */ - switch (epdrv->requested_id) { - case EARLY_PLATFORM_ID_ERROR: - case EARLY_PLATFORM_ID_UNSET: - break; - default: - if (epdrv->requested_id == id) - match_id = EARLY_PLATFORM_ID_UNSET; - } - } - - switch (match_id) { - case EARLY_PLATFORM_ID_ERROR: - pr_warn("%s: unable to parse %s parameter\n", - class_str, epdrv->pdrv->driver.name); - /* fall-through */ - case EARLY_PLATFORM_ID_UNSET: - match = NULL; - break; - default: - match = early_platform_match(epdrv, match_id); - } - - if (match) { - /* - * Set up a sensible init_name to enable - * dev_name() and others to be used before the - * rest of the driver core is initialized. - */ - if (!match->dev.init_name && slab_is_available()) { - if (match->id != -1) - match->dev.init_name = - kasprintf(GFP_KERNEL, "%s.%d", - match->name, - match->id); - else - match->dev.init_name = - kasprintf(GFP_KERNEL, "%s", - match->name); - - if (!match->dev.init_name) - return -ENOMEM; - } - - if (epdrv->pdrv->probe(match)) - pr_warn("%s: unable to probe %s early.\n", - class_str, match->name); - else - n++; - } - - if (n >= nr_probe) - break; - } - - if (left) - return n; - else - return -ENODEV; -} - -/** - * early_platform_driver_probe - probe a class of registered drivers - * @class_str: string to identify early platform driver class - * @nr_probe: number of platform devices to successfully probe before exiting - * @user_only: only probe user specified early platform devices - * - * Used by architecture code to probe registered early platform drivers - * within a certain class. For probe to happen a registered early platform - * device matching a registered early platform driver is needed. - */ -int __init early_platform_driver_probe(char *class_str, - int nr_probe, - int user_only) -{ - int k, n, i; - - n = 0; - for (i = -2; n < nr_probe; i++) { - k = early_platform_driver_probe_id(class_str, i, nr_probe - n); - - if (k < 0) - break; - - n += k; - - if (user_only) - break; - } - - return n; -} - -/** - * early_platform_cleanup - clean up early platform code - */ -void __init early_platform_cleanup(void) -{ - struct platform_device *pd, *pd2; - - /* clean up the devres list used to chain devices */ - list_for_each_entry_safe(pd, pd2, &early_platform_device_list, - dev.devres_head) { - list_del(&pd->dev.devres_head); - memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); - } -} - -- cgit v1.2.3 From ec4e29068839e00ff99ae94ccbb46123f0a0ba9d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 9 Oct 2019 11:37:46 +0200 Subject: driver core: simplify definitions of platform_get_irq* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq_optional is just a wrapper for __platform_get_irq. So rename __platform_get_irq to platform_get_irq_optional and drop platform_get_irq_optional's previous implementation. This way there is one function and one indirection less without loss of functionality. Signed-off-by: Uwe Kleine-König Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20191009093746.12095-1-uwe@kleine-koenig.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'drivers/base/platform.c') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index be1e67ee3af6..b0263dcf068f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -80,7 +80,24 @@ void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); #endif /* CONFIG_HAS_IOMEM */ -static int __platform_get_irq(struct platform_device *dev, unsigned int num) +/** + * 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) { #ifdef CONFIG_SPARC /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ @@ -144,6 +161,7 @@ static int __platform_get_irq(struct platform_device *dev, unsigned int num) return -ENXIO; #endif } +EXPORT_SYMBOL_GPL(platform_get_irq_optional); /** * platform_get_irq - get an IRQ for a device @@ -165,7 +183,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) { int ret; - ret = __platform_get_irq(dev, num); + ret = platform_get_irq_optional(dev, num); if (ret < 0 && ret != -EPROBE_DEFER) dev_err(&dev->dev, "IRQ index %u not found\n", num); @@ -173,29 +191,6 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) } 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 @@ -206,7 +201,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_optional(dev, nr)) >= 0) nr++; if (ret == -EPROBE_DEFER) -- cgit v1.2.3 From bb6243b4f73d29f8c8faf8f805a2042ac3973b71 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Oct 2019 10:43:14 +0200 Subject: drivers: platform: provide devm_platform_ioremap_resource_wc() Provide a write-combined variant of devm_platform_ioremap_resource(). Signed-off-by: Bartosz Golaszewski Reviewed-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191022084318.22256-5-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/driver-model/devres.rst | 1 + drivers/base/platform.c | 19 ++++++++++++++++++- include/linux/platform_device.h | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/base/platform.c') diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index e605bb9df6e1..480b78ca3871 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -318,6 +318,7 @@ IOMAP devm_ioremap_resource() : checks resource, requests memory region, ioremaps devm_ioremap_resource_wc() devm_platform_ioremap_resource() : calls devm_ioremap_resource() for platform device + devm_platform_ioremap_resource_wc() devm_iounmap() pcim_iomap() pcim_iomap_regions() : do request_region() and iomap() on multiple BARs diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e0ca682a756d..28eb71967f17 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -60,6 +60,7 @@ struct resource *platform_get_resource(struct platform_device *dev, } EXPORT_SYMBOL_GPL(platform_get_resource); +#ifdef CONFIG_HAS_IOMEM /** * devm_platform_ioremap_resource - call devm_ioremap_resource() for a platform * device @@ -68,7 +69,6 @@ EXPORT_SYMBOL_GPL(platform_get_resource); * resource management * @index: resource index */ -#ifdef CONFIG_HAS_IOMEM void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index) { @@ -78,6 +78,23 @@ void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, return devm_ioremap_resource(&pdev->dev, res); } EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); + +/** + * devm_platform_ioremap_resource_wc - write-combined variant of + * devm_platform_ioremap_resource() + * + * @pdev: platform device to use both for memory resource lookup as well as + * resource management + * @index: resource index + */ +void __iomem *devm_platform_ioremap_resource_wc(struct platform_device *pdev, + unsigned int index) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, index); + return devm_ioremap_resource_wc(&pdev->dev, res); +} #endif /* CONFIG_HAS_IOMEM */ /** diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 51fb7fc28587..91fcdbbae89d 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -57,6 +57,9 @@ platform_find_device_by_driver(struct device *start, extern void __iomem * devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index); +extern void __iomem * +devm_platform_ioremap_resource_wc(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 *); -- cgit v1.2.3 From c9c8641d3ebd79274af75f7df3e6a9c6cc8a66e9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 22 Oct 2019 10:43:16 +0200 Subject: drivers: provide devm_platform_ioremap_resource_byname() Provide a variant of devm_platform_ioremap_resource() that allows to lookup resources from platform devices by name rather than by index. Signed-off-by: Bartosz Golaszewski Reviewed-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191022084318.22256-7-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/driver-model/devres.rst | 1 + drivers/base/platform.c | 20 ++++++++++++++++++++ include/linux/platform_device.h | 3 +++ 3 files changed, 24 insertions(+) (limited to 'drivers/base/platform.c') diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 480b78ca3871..4ab193319d8c 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -319,6 +319,7 @@ IOMAP devm_ioremap_resource_wc() devm_platform_ioremap_resource() : calls devm_ioremap_resource() for platform device devm_platform_ioremap_resource_wc() + devm_platform_ioremap_resource_byname() devm_iounmap() pcim_iomap() pcim_iomap_regions() : do request_region() and iomap() on multiple BARs diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 28eb71967f17..1b8a20466eef 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -95,6 +95,26 @@ void __iomem *devm_platform_ioremap_resource_wc(struct platform_device *pdev, res = platform_get_resource(pdev, IORESOURCE_MEM, index); return devm_ioremap_resource_wc(&pdev->dev, res); } + +/** + * devm_platform_ioremap_resource_byname - call devm_ioremap_resource for + * a platform device, retrieve the + * resource by name + * + * @pdev: platform device to use both for memory resource lookup as well as + * resource management + * @name: name of the resource + */ +void __iomem * +devm_platform_ioremap_resource_byname(struct platform_device *pdev, + const char *name) +{ + struct resource *res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + return devm_ioremap_resource(&pdev->dev, res); +} +EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname); #endif /* CONFIG_HAS_IOMEM */ /** diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 91fcdbbae89d..276a03c24691 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -60,6 +60,9 @@ devm_platform_ioremap_resource(struct platform_device *pdev, extern void __iomem * devm_platform_ioremap_resource_wc(struct platform_device *pdev, unsigned int index); +extern void __iomem * +devm_platform_ioremap_resource_byname(struct platform_device *pdev, + const char *name); 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 *); -- cgit v1.2.3 From 492c88720d36eb662f9f10c1633f7726fbb07fc4 Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Tue, 12 Nov 2019 13:41:56 -0800 Subject: driver core: platform: use the correct callback type for bus_find_device platform_find_device_by_driver calls bus_find_device and passes platform_match as the callback function. Casting the function to a mismatching type trips indirect call Control-Flow Integrity (CFI) checking. This change adds a callback function with the correct type and instead of casting the function, explicitly casts the second parameter to struct device_driver* as expected by platform_match. Fixes: 36f3313d6bff9 ("platform: Add platform_find_device_by_driver() helper") Signed-off-by: Sami Tolvanen Reviewed-by: Kees Cook Cc: stable Link: https://lore.kernel.org/r/20191112214156.3430-1-samitolvanen@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/base/platform.c') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1b8a20466eef..d51dc35749c6 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1310,6 +1310,11 @@ struct bus_type platform_bus_type = { }; EXPORT_SYMBOL_GPL(platform_bus_type); +static inline int __platform_match(struct device *dev, const void *drv) +{ + return platform_match(dev, (struct device_driver *)drv); +} + /** * platform_find_device_by_driver - Find a platform device with a given * driver. @@ -1320,7 +1325,7 @@ struct device *platform_find_device_by_driver(struct device *start, const struct device_driver *drv) { return bus_find_device(&platform_bus_type, start, drv, - (void *)platform_match); + __platform_match); } EXPORT_SYMBOL_GPL(platform_find_device_by_driver); -- cgit v1.2.3 From 71564a26e3e9d29d3d8901eb32647c2c3a807e1f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 23 Oct 2019 15:25:05 +0300 Subject: driver core: platform: Declare ret variable only once We may define ret variable only once and avoid adding it each time platform_get_irq_optional() get extended. For the sake of consistency do the same in __platform_get_irq_byname(). Signed-off-by: Andy Shevchenko Reviewed-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20191023122505.64684-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/base/platform.c') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d51dc35749c6..7c532548b0a6 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -143,9 +143,9 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num) return dev->archdata.irqs[num]; #else struct resource *r; - if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { - int ret; + int ret; + if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { ret = of_irq_get(dev->dev.of_node, num); if (ret > 0 || ret == -EPROBE_DEFER) return ret; @@ -154,8 +154,6 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num) r = platform_get_resource(dev, IORESOURCE_IRQ, num); if (has_acpi_companion(&dev->dev)) { if (r && r->flags & IORESOURCE_DISABLED) { - int ret; - ret = acpi_irq_get(ACPI_HANDLE(&dev->dev), num, r); if (ret) return ret; @@ -188,8 +186,7 @@ int platform_get_irq_optional(struct platform_device *dev, unsigned int num) * allows a common code path across either kind of resource. */ if (num == 0 && has_acpi_companion(&dev->dev)) { - int ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num); - + ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num); /* Our callers expect -ENXIO for missing IRQs. */ if (ret >= 0 || ret == -EPROBE_DEFER) return ret; @@ -277,10 +274,9 @@ static int __platform_get_irq_byname(struct platform_device *dev, const char *name) { struct resource *r; + int ret; if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { - int ret; - ret = of_irq_get_byname(dev->dev.of_node, name); if (ret > 0 || ret == -EPROBE_DEFER) return ret; -- cgit v1.2.3 From eecd37e105f0137af0d1b726bf61ff35d1d7d2eb Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 3 Dec 2019 12:58:52 -0800 Subject: drivers: Fix boot problem on SuperH SuperH images crash too eearly to display any console output. Bisect points to commit 507fd01d5333 ("drivers: move the early platform device support to arch/sh"). An analysis of that patch suggests that early_platform_cleanup() is now called at the wrong time. Restoring its call point fixes the problem. Cc: Bartosz Golaszewski Fixes: 507fd01d5333 ("drivers: move the early platform device support to arch/sh") Tested-by: Geert Uytterhoeven Signed-off-by: Guenter Roeck Acked-by: Rob Landley Link: https://lore.kernel.org/r/20191203205852.15659-1-linux@roeck-us.net Signed-off-by: Greg Kroah-Hartman --- arch/sh/drivers/platform_early.c | 11 ++--------- drivers/base/platform.c | 4 ++++ 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/base/platform.c') diff --git a/arch/sh/drivers/platform_early.c b/arch/sh/drivers/platform_early.c index f6d148451dfc..f3dc3f25b3ff 100644 --- a/arch/sh/drivers/platform_early.c +++ b/arch/sh/drivers/platform_early.c @@ -325,9 +325,9 @@ int __init sh_early_platform_driver_probe(char *class_str, } /** - * sh_early_platform_cleanup - clean up early platform code + * early_platform_cleanup - clean up early platform code */ -static int __init sh_early_platform_cleanup(void) +void __init early_platform_cleanup(void) { struct platform_device *pd, *pd2; @@ -337,11 +337,4 @@ static int __init sh_early_platform_cleanup(void) list_del(&pd->dev.devres_head); memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); } - - return 0; } -/* - * This must happen once after all early devices are probed but before probing - * real platform devices. - */ -subsys_initcall(sh_early_platform_cleanup); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 7c532548b0a6..cf6b6b722e5c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1325,10 +1325,14 @@ struct device *platform_find_device_by_driver(struct device *start, } EXPORT_SYMBOL_GPL(platform_find_device_by_driver); +void __weak __init early_platform_cleanup(void) { } + int __init platform_bus_init(void) { int error; + early_platform_cleanup(); + error = device_register(&platform_bus); if (error) { put_device(&platform_bus); -- cgit v1.2.3