linux-stable/drivers/net/dsa/ocelot/ocelot_ext.c
Uwe Kleine-König 68ace16ce3 net: dsa: ocelot: 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() is renamed to .remove().

Trivially convert these drivers 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>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-09-20 10:25:57 +01:00

162 lines
3.6 KiB
C

// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright 2021-2022 Innovative Advantage Inc.
*/
#include <linux/mfd/ocelot.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <soc/mscc/ocelot.h>
#include <soc/mscc/vsc7514_regs.h>
#include "felix.h"
#define VSC7514_NUM_PORTS 11
#define OCELOT_PORT_MODE_SERDES (OCELOT_PORT_MODE_SGMII | \
OCELOT_PORT_MODE_QSGMII)
static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = {
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_SERDES,
OCELOT_PORT_MODE_SERDES,
OCELOT_PORT_MODE_SERDES,
OCELOT_PORT_MODE_SERDES,
OCELOT_PORT_MODE_SERDES,
OCELOT_PORT_MODE_SGMII,
OCELOT_PORT_MODE_SERDES,
};
static const struct ocelot_ops ocelot_ext_ops = {
.reset = ocelot_reset,
.wm_enc = ocelot_wm_enc,
.wm_dec = ocelot_wm_dec,
.wm_stat = ocelot_wm_stat,
.port_to_netdev = felix_port_to_netdev,
.netdev_to_port = felix_netdev_to_port,
};
static const char * const vsc7512_resource_names[TARGET_MAX] = {
[SYS] = "sys",
[REW] = "rew",
[S0] = "s0",
[S1] = "s1",
[S2] = "s2",
[QS] = "qs",
[QSYS] = "qsys",
[ANA] = "ana",
};
static const struct felix_info vsc7512_info = {
.resource_names = vsc7512_resource_names,
.regfields = vsc7514_regfields,
.map = vsc7514_regmap,
.ops = &ocelot_ext_ops,
.vcap = vsc7514_vcap_props,
.num_mact_rows = 1024,
.num_ports = VSC7514_NUM_PORTS,
.num_tx_queues = OCELOT_NUM_TC,
.port_modes = vsc7512_port_modes,
.phylink_mac_config = ocelot_phylink_mac_config,
.configure_serdes = ocelot_port_configure_serdes,
};
static int ocelot_ext_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dsa_switch *ds;
struct ocelot *ocelot;
struct felix *felix;
int err;
felix = kzalloc(sizeof(*felix), GFP_KERNEL);
if (!felix)
return -ENOMEM;
dev_set_drvdata(dev, felix);
ocelot = &felix->ocelot;
ocelot->dev = dev;
ocelot->num_flooding_pgids = 1;
felix->info = &vsc7512_info;
ds = kzalloc(sizeof(*ds), GFP_KERNEL);
if (!ds) {
err = -ENOMEM;
dev_err_probe(dev, err, "Failed to allocate DSA switch\n");
goto err_free_felix;
}
ds->dev = dev;
ds->num_ports = felix->info->num_ports;
ds->num_tx_queues = felix->info->num_tx_queues;
ds->ops = &felix_switch_ops;
ds->priv = ocelot;
felix->ds = ds;
felix->tag_proto = DSA_TAG_PROTO_OCELOT;
err = dsa_register_switch(ds);
if (err) {
dev_err_probe(dev, err, "Failed to register DSA switch\n");
goto err_free_ds;
}
return 0;
err_free_ds:
kfree(ds);
err_free_felix:
kfree(felix);
return err;
}
static void ocelot_ext_remove(struct platform_device *pdev)
{
struct felix *felix = dev_get_drvdata(&pdev->dev);
if (!felix)
return;
dsa_unregister_switch(felix->ds);
kfree(felix->ds);
kfree(felix);
}
static void ocelot_ext_shutdown(struct platform_device *pdev)
{
struct felix *felix = dev_get_drvdata(&pdev->dev);
if (!felix)
return;
dsa_switch_shutdown(felix->ds);
dev_set_drvdata(&pdev->dev, NULL);
}
static const struct of_device_id ocelot_ext_switch_of_match[] = {
{ .compatible = "mscc,vsc7512-switch" },
{ },
};
MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match);
static struct platform_driver ocelot_ext_switch_driver = {
.driver = {
.name = "ocelot-ext-switch",
.of_match_table = ocelot_ext_switch_of_match,
},
.probe = ocelot_ext_probe,
.remove_new = ocelot_ext_remove,
.shutdown = ocelot_ext_shutdown,
};
module_platform_driver(ocelot_ext_switch_driver);
MODULE_DESCRIPTION("External Ocelot Switch driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(MFD_OCELOT);