[lvc-project] [PATCH] wifi: brcmfmac: avoid calling platform_driver_unregister() more than once

Dmitry Antipov dmantipov at yandex.ru
Tue Apr 15 16:09:26 MSK 2025


On 4/14/25 12:22 PM, Arend van Spriel wrote:

> When the platform_driver_probe() fails it means that brcmfmac_pdata will
> be NULL so it provides the same info as the returned error. So the
> net result is the same and no platform_driver_unregister() will be called.
I'm not sure whether the following model is 100% accurate against the real
driver, but it always crashes (in platform_driver_unregister() explicitly
called from module init function) when non-zero (say, -ENOMEM) is returned
from probe (e.g. t_platform_driver_probe()) function:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>

static struct platform_device t_platform_device = {
	.name = "testdev",
};

struct t_driver_data {
	int dummy;
} *t_pdata = NULL, driver_data = { .dummy = 1 };

static void t_platform_driver_remove(struct platform_device *pd)
{
	printk(KERN_ERR "remove platform device@%p\n", pd);
}

static struct platform_driver t_pd = {
	.remove = t_platform_driver_remove,
	.driver = {
		.name = "testdev",
	}
};

static int t_platform_driver_probe(struct platform_device *pd)
{
	printk(KERN_ERR "probe platform device@%p\n", pd);
	t_pdata = &driver_data;
	return 0;
}

static int t_always_error(void)
{
	return -ENODATA;
}

static int __init
t_platform_driver_init(void)
{
	int err;

	err = platform_device_register(&t_platform_device);
	if (err) {
		printk(KERN_ERR "unable to register platform device\n");
		return err;
	}

	err = platform_driver_probe(&t_pd, t_platform_driver_probe);

	if (err == -ENODEV)
		printk(KERN_ERR "No platform data");

	err = t_always_error();

	if (err) {
		if (t_pdata) {
			printk(KERN_ERR "going to unregister platform driver@%p\n", &t_pd);
			platform_driver_unregister(&t_pd);
		}
		platform_device_unregister(&t_platform_device);
	}
	return err;
}

static void __exit
t_platform_driver_exit(void)
{
	if (t_pdata)
		platform_driver_unregister(&t_pd);

	platform_device_unregister(&t_platform_device);
}

module_init(t_platform_driver_init);
module_exit(t_platform_driver_exit);
MODULE_LICENSE("GPL");

Dmitry



More information about the lvc-project mailing list