summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-13 10:05:17 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-07-12 12:05:22 +1000
commit8ef9ccf81044a1e31d116b5d4972d5b65ae10846 (patch)
treeb547165fa27419b423f16bbe0d067fcaf7458566
parent265aac26bcd4a2a79d08d2bdcc08cf1653fd4248 (diff)
downloadlinux-8ef9ccf81044a1e31d116b5d4972d5b65ae10846.tar.bz2
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>
-rw-r--r--drivers/fsi/fsi-master-gpio.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index a589a44bd805..c4a06210ddce 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -786,32 +786,44 @@ static ssize_t external_mode_store(struct device *dev,
static DEVICE_ATTR(external_mode, 0664,
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)
{
struct fsi_master_gpio *master;
struct gpio_desc *gpio;
int rc;
- master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
+ master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master)
return -ENOMEM;
master->dev = &pdev->dev;
master->master.dev.parent = 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;
gpio = devm_gpiod_get(&pdev->dev, "clock", 0);
if (IS_ERR(gpio)) {
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;
gpio = devm_gpiod_get(&pdev->dev, "data", 0);
if (IS_ERR(gpio)) {
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;
@@ -819,21 +831,24 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
gpio = devm_gpiod_get_optional(&pdev->dev, "trans", 0);
if (IS_ERR(gpio)) {
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;
gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 0);
if (IS_ERR(gpio)) {
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;
gpio = devm_gpiod_get_optional(&pdev->dev, "mux", 0);
if (IS_ERR(gpio)) {
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;
@@ -863,27 +878,29 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
rc = device_create_file(&pdev->dev, &dev_attr_external_mode);
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)
{
struct fsi_master_gpio *master = platform_get_drvdata(pdev);
- devm_gpiod_put(&pdev->dev, master->gpio_clk);
- 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);
+ device_remove_file(&pdev->dev, &dev_attr_external_mode);
- of_node_put(master->master.dev.of_node);
+ fsi_master_unregister(&master->master);
return 0;
}