fsi: master-gpio: Add missing release function

The embedded struct device needs a release function to be
able to successfully remove the driver.

We remove the devm_gpiod_put() as they are unnecessary
(the resources will be released automatically) and because
fsi_master_unregister() will cause the master structure to
be freed.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
This commit is contained in:
Benjamin Herrenschmidt 2018-06-13 10:05:17 +10:00
parent 265aac26bc
commit 8ef9ccf810
1 changed files with 35 additions and 18 deletions

View File

@ -786,32 +786,44 @@ static ssize_t external_mode_store(struct device *dev,
static DEVICE_ATTR(external_mode, 0664, static DEVICE_ATTR(external_mode, 0664,
external_mode_show, external_mode_store); external_mode_show, external_mode_store);
static void fsi_master_gpio_release(struct device *dev)
{
struct fsi_master_gpio *master = to_fsi_master_gpio(dev_to_fsi_master(dev));
of_node_put(dev_of_node(master->dev));
kfree(master);
}
static int fsi_master_gpio_probe(struct platform_device *pdev) static int fsi_master_gpio_probe(struct platform_device *pdev)
{ {
struct fsi_master_gpio *master; struct fsi_master_gpio *master;
struct gpio_desc *gpio; struct gpio_desc *gpio;
int rc; int rc;
master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
master->dev = &pdev->dev; master->dev = &pdev->dev;
master->master.dev.parent = master->dev; master->master.dev.parent = master->dev;
master->master.dev.of_node = of_node_get(dev_of_node(master->dev)); master->master.dev.of_node = of_node_get(dev_of_node(master->dev));
master->master.dev.release = fsi_master_gpio_release;
master->last_addr = LAST_ADDR_INVALID; master->last_addr = LAST_ADDR_INVALID;
gpio = devm_gpiod_get(&pdev->dev, "clock", 0); gpio = devm_gpiod_get(&pdev->dev, "clock", 0);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get clock gpio\n"); dev_err(&pdev->dev, "failed to get clock gpio\n");
return PTR_ERR(gpio); rc = PTR_ERR(gpio);
goto err_free;
} }
master->gpio_clk = gpio; master->gpio_clk = gpio;
gpio = devm_gpiod_get(&pdev->dev, "data", 0); gpio = devm_gpiod_get(&pdev->dev, "data", 0);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get data gpio\n"); dev_err(&pdev->dev, "failed to get data gpio\n");
return PTR_ERR(gpio); rc = PTR_ERR(gpio);
goto err_free;
} }
master->gpio_data = gpio; master->gpio_data = gpio;
@ -819,21 +831,24 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
gpio = devm_gpiod_get_optional(&pdev->dev, "trans", 0); gpio = devm_gpiod_get_optional(&pdev->dev, "trans", 0);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get trans gpio\n"); dev_err(&pdev->dev, "failed to get trans gpio\n");
return PTR_ERR(gpio); rc = PTR_ERR(gpio);
goto err_free;
} }
master->gpio_trans = gpio; master->gpio_trans = gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 0); gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 0);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get enable gpio\n"); dev_err(&pdev->dev, "failed to get enable gpio\n");
return PTR_ERR(gpio); rc = PTR_ERR(gpio);
goto err_free;
} }
master->gpio_enable = gpio; master->gpio_enable = gpio;
gpio = devm_gpiod_get_optional(&pdev->dev, "mux", 0); gpio = devm_gpiod_get_optional(&pdev->dev, "mux", 0);
if (IS_ERR(gpio)) { if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to get mux gpio\n"); dev_err(&pdev->dev, "failed to get mux gpio\n");
return PTR_ERR(gpio); rc = PTR_ERR(gpio);
goto err_free;
} }
master->gpio_mux = gpio; master->gpio_mux = gpio;
@ -863,27 +878,29 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
rc = device_create_file(&pdev->dev, &dev_attr_external_mode); rc = device_create_file(&pdev->dev, &dev_attr_external_mode);
if (rc) if (rc)
return rc; goto err_free;
return fsi_master_register(&master->master); rc = fsi_master_register(&master->master);
if (rc) {
device_remove_file(&pdev->dev, &dev_attr_external_mode);
put_device(&master->master.dev);
return rc;
}
return 0;
err_free:
kfree(master);
return rc;
} }
static int fsi_master_gpio_remove(struct platform_device *pdev) static int fsi_master_gpio_remove(struct platform_device *pdev)
{ {
struct fsi_master_gpio *master = platform_get_drvdata(pdev); struct fsi_master_gpio *master = platform_get_drvdata(pdev);
devm_gpiod_put(&pdev->dev, master->gpio_clk); device_remove_file(&pdev->dev, &dev_attr_external_mode);
devm_gpiod_put(&pdev->dev, master->gpio_data);
if (master->gpio_trans)
devm_gpiod_put(&pdev->dev, master->gpio_trans);
if (master->gpio_enable)
devm_gpiod_put(&pdev->dev, master->gpio_enable);
if (master->gpio_mux)
devm_gpiod_put(&pdev->dev, master->gpio_mux);
fsi_master_unregister(&master->master);
of_node_put(master->master.dev.of_node); fsi_master_unregister(&master->master);
return 0; return 0;
} }