linux-stable/drivers/crypto/ccp/sp-platform.c
Uwe Kleine-König 11575ef99f crypto: ccp/sp - Convert to platform remove callback returning void
The .remove() callback for a platform driver returns an int which makes
many driver authors wrongly assume it's possible to do error handling by
returning an error code. However the value returned is ignored (apart
from emitting a warning) and this typically results in resource leaks.

To improve here there is a quest to make the remove callback return
void. In the first step of this quest all drivers are converted to
.remove_new(), which already returns void. Eventually after all drivers
are converted, .remove_new() will be renamed to .remove().

Trivially convert this driver from always returning zero in the remove
callback to the void returning variant.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2023-10-27 18:04:26 +08:00

238 lines
4.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD Secure Processor device driver
*
* Copyright (C) 2014,2018 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/dma-mapping.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/ccp.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/acpi.h>
#include "ccp-dev.h"
struct sp_platform {
int coherent;
unsigned int irq_count;
};
static const struct sp_dev_vdata dev_vdata[] = {
{
.bar = 0,
#ifdef CONFIG_CRYPTO_DEV_SP_CCP
.ccp_vdata = &ccpv3_platform,
#endif
},
};
#ifdef CONFIG_ACPI
static const struct acpi_device_id sp_acpi_match[] = {
{ "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
{ },
};
MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
#endif
#ifdef CONFIG_OF
static const struct of_device_id sp_of_match[] = {
{ .compatible = "amd,ccp-seattle-v1a",
.data = (const void *)&dev_vdata[0] },
{ },
};
MODULE_DEVICE_TABLE(of, sp_of_match);
#endif
static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
{
#ifdef CONFIG_OF
const struct of_device_id *match;
match = of_match_node(sp_of_match, pdev->dev.of_node);
if (match && match->data)
return (struct sp_dev_vdata *)match->data;
#endif
return NULL;
}
static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
{
#ifdef CONFIG_ACPI
const struct acpi_device_id *match;
match = acpi_match_device(sp_acpi_match, &pdev->dev);
if (match && match->driver_data)
return (struct sp_dev_vdata *)match->driver_data;
#endif
return NULL;
}
static int sp_get_irqs(struct sp_device *sp)
{
struct sp_platform *sp_platform = sp->dev_specific;
struct device *dev = sp->dev;
struct platform_device *pdev = to_platform_device(dev);
int ret;
sp_platform->irq_count = platform_irq_count(pdev);
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_notice(dev, "unable to get IRQ (%d)\n", ret);
return ret;
}
sp->psp_irq = ret;
if (sp_platform->irq_count == 1) {
sp->ccp_irq = ret;
} else {
ret = platform_get_irq(pdev, 1);
if (ret < 0) {
dev_notice(dev, "unable to get IRQ (%d)\n", ret);
return ret;
}
sp->ccp_irq = ret;
}
return 0;
}
static int sp_platform_probe(struct platform_device *pdev)
{
struct sp_device *sp;
struct sp_platform *sp_platform;
struct device *dev = &pdev->dev;
enum dev_dma_attr attr;
int ret;
ret = -ENOMEM;
sp = sp_alloc_struct(dev);
if (!sp)
goto e_err;
sp_platform = devm_kzalloc(dev, sizeof(*sp_platform), GFP_KERNEL);
if (!sp_platform)
goto e_err;
sp->dev_specific = sp_platform;
sp->dev_vdata = pdev->dev.of_node ? sp_get_of_version(pdev)
: sp_get_acpi_version(pdev);
if (!sp->dev_vdata) {
ret = -ENODEV;
dev_err(dev, "missing driver data\n");
goto e_err;
}
sp->io_map = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sp->io_map)) {
ret = PTR_ERR(sp->io_map);
goto e_err;
}
attr = device_get_dma_attr(dev);
if (attr == DEV_DMA_NOT_SUPPORTED) {
dev_err(dev, "DMA is not supported");
goto e_err;
}
sp_platform->coherent = (attr == DEV_DMA_COHERENT);
if (sp_platform->coherent)
sp->axcache = CACHE_WB_NO_ALLOC;
else
sp->axcache = CACHE_NONE;
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
if (ret) {
dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
goto e_err;
}
ret = sp_get_irqs(sp);
if (ret)
goto e_err;
dev_set_drvdata(dev, sp);
ret = sp_init(sp);
if (ret)
goto e_err;
dev_notice(dev, "enabled\n");
return 0;
e_err:
dev_notice(dev, "initialization failed\n");
return ret;
}
static void sp_platform_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev);
sp_destroy(sp);
dev_notice(dev, "disabled\n");
}
#ifdef CONFIG_PM
static int sp_platform_suspend(struct platform_device *pdev,
pm_message_t state)
{
struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev);
return sp_suspend(sp);
}
static int sp_platform_resume(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev);
return sp_resume(sp);
}
#endif
static struct platform_driver sp_platform_driver = {
.driver = {
.name = "ccp",
#ifdef CONFIG_ACPI
.acpi_match_table = sp_acpi_match,
#endif
#ifdef CONFIG_OF
.of_match_table = sp_of_match,
#endif
},
.probe = sp_platform_probe,
.remove_new = sp_platform_remove,
#ifdef CONFIG_PM
.suspend = sp_platform_suspend,
.resume = sp_platform_resume,
#endif
};
int sp_platform_init(void)
{
return platform_driver_register(&sp_platform_driver);
}
void sp_platform_exit(void)
{
platform_driver_unregister(&sp_platform_driver);
}