mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
Networking fixes for 5.15-rc3.
Current release - regressions: - dsa: bcm_sf2: fix array overrun in bcm_sf2_num_active_ports() Previous releases - regressions: - introduce a shutdown method to mdio device drivers, and make DSA switch drivers compatible with masters disappearing on shutdown; preventing infinite reference wait - fix issues in mdiobus users related to ->shutdown vs ->remove - virtio-net: fix pages leaking when building skb in big mode - xen-netback: correct success/error reporting for the SKB-with-fraglist - dsa: tear down devlink port regions when tearing down the devlink port on error - nexthop: fix division by zero while replacing a resilient group - hns3: check queue, vf, vlan ids range before using Previous releases - always broken: - napi: fix race against netpoll causing NAPI getting stuck - mlx4_en: ensure link operstate is updated even if link comes up before netdev registration - bnxt_en: fix TX timeout when TX ring size is set to the smallest - enetc: fix illegal access when reading affinity_hint; prevent oops on sysfs access - mtk_eth_soc: avoid creating duplicate offload entries Misc: - core: correct the sock::sk_lock.owned lockdep annotations Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmFMr4MACgkQMUZtbf5S Irv6Ag/+Ml4q6/IVO0jBppztZO1RrSalb3YE9JjPQyMchauVcdcADNpYF+Jo/gcH 4q+/Oikfp6gkQpJTFd0Y9X7UhwA4Jm4wWtEisqc6PJeHOagDZmVUn353WtgpnCNL CgYBfa5k3msGudkqgeXIyiP/2sekBevTy+fOptubLZClyBrEwNUUUZBlpT9aI9Sj ru1eMYklfcxP60AQgNhqq6ZwJnRELgN75fSR6ypVCGcRnTK4UGL/b6TvnPYn8uYY zeNuMZZzYZK5B73tC6rWpteHWZ7VW3Km0WvIKs+ORM8nYchz/EprKZ0HCLPYrWvf ib5Wi7HyL7/n9k9NUTCGrQY3tkOWNzXOepjpiBZPqCG9r2hc3JSR7Q2lFwL+gKv/ sh2y+T2xfp0WFGmG2XiU2MgnkypMSKah1sC/XRE7YLw02vPAnWQxxl/KVNek4j7M CH/Tg9ErVKDRLN7KO/kKl3s8I8N4hdctms/YUt9QD5J9Rw/Jqwr/79bq1uLy6d4o //ipmCTHex57Nvy80PtgcuKJhoeqGwR/Av6BvBMRZ1SOYs/C6q45skHTlYyiNY3+ Dyj9+nfrhsyE835GKPe8lqBFZONBXpXw+EUNXeYRiv0Pcd+JKek07bbajSQVSpd8 8nqQwylpGII0iPGyOc9wKajzh7O5W2odFIdOwtY/5yVjrcFgBd0= =VcL3 -----END PGP SIGNATURE----- Merge tag 'net-5.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Current release - regressions: - dsa: bcm_sf2: fix array overrun in bcm_sf2_num_active_ports() Previous releases - regressions: - introduce a shutdown method to mdio device drivers, and make DSA switch drivers compatible with masters disappearing on shutdown; preventing infinite reference wait - fix issues in mdiobus users related to ->shutdown vs ->remove - virtio-net: fix pages leaking when building skb in big mode - xen-netback: correct success/error reporting for the SKB-with-fraglist - dsa: tear down devlink port regions when tearing down the devlink port on error - nexthop: fix division by zero while replacing a resilient group - hns3: check queue, vf, vlan ids range before using Previous releases - always broken: - napi: fix race against netpoll causing NAPI getting stuck - mlx4_en: ensure link operstate is updated even if link comes up before netdev registration - bnxt_en: fix TX timeout when TX ring size is set to the smallest - enetc: fix illegal access when reading affinity_hint; prevent oops on sysfs access - mtk_eth_soc: avoid creating duplicate offload entries Misc: - core: correct the sock::sk_lock.owned lockdep annotations" * tag 'net-5.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (51 commits) atlantic: Fix issue in the pm resume flow. net/mlx4_en: Don't allow aRFS for encapsulated packets net: mscc: ocelot: fix forwarding from BLOCKING ports remaining enabled net: ethernet: mtk_eth_soc: avoid creating duplicate offload entries nfc: st-nci: Add SPI ID matching DT compatible MAINTAINERS: remove Guvenc Gulce as net/smc maintainer nexthop: Fix memory leaks in nexthop notification chain listeners mptcp: ensure tx skbs always have the MPTCP ext qed: rdma - don't wait for resources under hw error recovery flow s390/qeth: fix deadlock during failing recovery s390/qeth: Fix deadlock in remove_discipline s390/qeth: fix NULL deref in qeth_clear_working_pool_list() net: dsa: realtek: register the MDIO bus under devres net: dsa: don't allocate the slave_mii_bus using devres Doc: networking: Fox a typo in ice.rst net: dsa: fix dsa_tree_setup error path net/smc: fix 'workqueue leaked lock' in smc_conn_abort_work net/smc: add missing error check in smc_clc_prfx_set() net: hns3: fix a return value error in hclge_get_reset_status() net: hns3: check vlan id before using it ...
This commit is contained in:
commit
9bc62afe03
@ -851,7 +851,7 @@ NOTES:
|
||||
- 0x88A8 traffic will not be received unless VLAN stripping is disabled with
|
||||
the following command::
|
||||
|
||||
# ethool -K <ethX> rxvlan off
|
||||
# ethtool -K <ethX> rxvlan off
|
||||
|
||||
- 0x88A8/0x8100 double VLANs cannot be used with 0x8100 or 0x8100/0x8100 VLANS
|
||||
configured on the same port. 0x88a8/0x8100 traffic will not be received if
|
||||
|
@ -16955,7 +16955,6 @@ F: drivers/misc/sgi-xp/
|
||||
|
||||
SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
|
||||
M: Karsten Graul <kgraul@linux.ibm.com>
|
||||
M: Guvenc Gulce <guvenc@linux.ibm.com>
|
||||
L: linux-s390@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||
|
@ -55,7 +55,7 @@ int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
|
||||
int num_devices, const char *buf);
|
||||
|
||||
extern int ccwgroup_set_online(struct ccwgroup_device *gdev);
|
||||
extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);
|
||||
int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv);
|
||||
|
||||
extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
|
||||
extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
|
||||
|
@ -351,9 +351,25 @@ static int b53_mdio_probe(struct mdio_device *mdiodev)
|
||||
static void b53_mdio_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct b53_device *dev = dev_get_drvdata(&mdiodev->dev);
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
|
||||
dsa_unregister_switch(ds);
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
b53_switch_remove(dev);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void b53_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct b53_device *dev = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
b53_switch_shutdown(dev);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id b53_of_match[] = {
|
||||
@ -373,6 +389,7 @@ MODULE_DEVICE_TABLE(of, b53_of_match);
|
||||
static struct mdio_driver b53_mdio_driver = {
|
||||
.probe = b53_mdio_probe,
|
||||
.remove = b53_mdio_remove,
|
||||
.shutdown = b53_mdio_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "bcm53xx",
|
||||
.of_match_table = b53_of_match,
|
||||
|
@ -316,9 +316,21 @@ static int b53_mmap_remove(struct platform_device *pdev)
|
||||
if (dev)
|
||||
b53_switch_remove(dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b53_mmap_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct b53_device *dev = platform_get_drvdata(pdev);
|
||||
|
||||
if (dev)
|
||||
b53_switch_shutdown(dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id b53_mmap_of_table[] = {
|
||||
{ .compatible = "brcm,bcm3384-switch" },
|
||||
{ .compatible = "brcm,bcm6328-switch" },
|
||||
@ -331,6 +343,7 @@ MODULE_DEVICE_TABLE(of, b53_mmap_of_table);
|
||||
static struct platform_driver b53_mmap_driver = {
|
||||
.probe = b53_mmap_probe,
|
||||
.remove = b53_mmap_remove,
|
||||
.shutdown = b53_mmap_shutdown,
|
||||
.driver = {
|
||||
.name = "b53-switch",
|
||||
.of_match_table = b53_mmap_of_table,
|
||||
|
@ -228,6 +228,11 @@ static inline void b53_switch_remove(struct b53_device *dev)
|
||||
dsa_unregister_switch(dev->ds);
|
||||
}
|
||||
|
||||
static inline void b53_switch_shutdown(struct b53_device *dev)
|
||||
{
|
||||
dsa_switch_shutdown(dev->ds);
|
||||
}
|
||||
|
||||
#define b53_build_op(type_op_size, val_type) \
|
||||
static inline int b53_##type_op_size(struct b53_device *dev, u8 page, \
|
||||
u8 reg, val_type val) \
|
||||
|
@ -321,9 +321,21 @@ static int b53_spi_remove(struct spi_device *spi)
|
||||
if (dev)
|
||||
b53_switch_remove(dev);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b53_spi_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct b53_device *dev = spi_get_drvdata(spi);
|
||||
|
||||
if (dev)
|
||||
b53_switch_shutdown(dev);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id b53_spi_of_match[] = {
|
||||
{ .compatible = "brcm,bcm5325" },
|
||||
{ .compatible = "brcm,bcm5365" },
|
||||
@ -344,6 +356,7 @@ static struct spi_driver b53_spi_driver = {
|
||||
},
|
||||
.probe = b53_spi_probe,
|
||||
.remove = b53_spi_remove,
|
||||
.shutdown = b53_spi_shutdown,
|
||||
};
|
||||
|
||||
module_spi_driver(b53_spi_driver);
|
||||
|
@ -629,17 +629,34 @@ static int b53_srab_probe(struct platform_device *pdev)
|
||||
static int b53_srab_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct b53_device *dev = platform_get_drvdata(pdev);
|
||||
struct b53_srab_priv *priv = dev->priv;
|
||||
|
||||
b53_srab_intr_set(priv, false);
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
b53_srab_intr_set(dev->priv, false);
|
||||
b53_switch_remove(dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void b53_srab_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct b53_device *dev = platform_get_drvdata(pdev);
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
b53_switch_shutdown(dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static struct platform_driver b53_srab_driver = {
|
||||
.probe = b53_srab_probe,
|
||||
.remove = b53_srab_remove,
|
||||
.shutdown = b53_srab_shutdown,
|
||||
.driver = {
|
||||
.name = "b53-srab-switch",
|
||||
.of_match_table = b53_srab_of_match,
|
||||
|
@ -68,7 +68,7 @@ static unsigned int bcm_sf2_num_active_ports(struct dsa_switch *ds)
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
unsigned int port, count = 0;
|
||||
|
||||
for (port = 0; port < ARRAY_SIZE(priv->port_sts); port++) {
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
if (dsa_is_cpu_port(ds, port))
|
||||
continue;
|
||||
if (priv->port_sts[port].enabled)
|
||||
@ -1512,6 +1512,9 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
if (!priv)
|
||||
return 0;
|
||||
|
||||
priv->wol_ports_mask = 0;
|
||||
/* Disable interrupts */
|
||||
bcm_sf2_intr_disable(priv);
|
||||
@ -1523,6 +1526,8 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
|
||||
if (priv->type == BCM7278_DEVICE_ID)
|
||||
reset_control_assert(priv->rcdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1530,6 +1535,9 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
/* For a kernel about to be kexec'd we want to keep the GPHY on for a
|
||||
* successful MDIO bus scan to occur. If we did turn off the GPHY
|
||||
* before (e.g: port_disable), this will also power it back on.
|
||||
@ -1538,6 +1546,10 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
|
||||
*/
|
||||
if (priv->hw_params.num_gphy == 1)
|
||||
bcm_sf2_gphy_enable_set(priv->dev->ds, true);
|
||||
|
||||
dsa_switch_shutdown(priv->dev->ds);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -340,10 +340,29 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
|
||||
static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
struct dsa_loop_priv *ps = ds->priv;
|
||||
struct dsa_loop_priv *ps;
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
ps = ds->priv;
|
||||
|
||||
dsa_unregister_switch(ds);
|
||||
dev_put(ps->netdev);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void dsa_loop_drv_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static struct mdio_driver dsa_loop_drv = {
|
||||
@ -352,6 +371,7 @@ static struct mdio_driver dsa_loop_drv = {
|
||||
},
|
||||
.probe = dsa_loop_drv_probe,
|
||||
.remove = dsa_loop_drv_remove,
|
||||
.shutdown = dsa_loop_drv_shutdown,
|
||||
};
|
||||
|
||||
#define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
|
||||
|
@ -1916,6 +1916,9 @@ static int hellcreek_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct hellcreek *hellcreek = platform_get_drvdata(pdev);
|
||||
|
||||
if (!hellcreek)
|
||||
return 0;
|
||||
|
||||
hellcreek_hwtstamp_free(hellcreek);
|
||||
hellcreek_ptp_free(hellcreek);
|
||||
dsa_unregister_switch(hellcreek->ds);
|
||||
@ -1924,6 +1927,18 @@ static int hellcreek_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hellcreek_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct hellcreek *hellcreek = platform_get_drvdata(pdev);
|
||||
|
||||
if (!hellcreek)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(hellcreek->ds);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct hellcreek_platform_data de1soc_r1_pdata = {
|
||||
.name = "r4c30",
|
||||
.num_ports = 4,
|
||||
@ -1946,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match);
|
||||
static struct platform_driver hellcreek_driver = {
|
||||
.probe = hellcreek_probe,
|
||||
.remove = hellcreek_remove,
|
||||
.shutdown = hellcreek_shutdown,
|
||||
.driver = {
|
||||
.name = "hellcreek",
|
||||
.of_match_table = hellcreek_of_match,
|
||||
|
@ -1379,6 +1379,12 @@ int lan9303_remove(struct lan9303 *chip)
|
||||
}
|
||||
EXPORT_SYMBOL(lan9303_remove);
|
||||
|
||||
void lan9303_shutdown(struct lan9303 *chip)
|
||||
{
|
||||
dsa_switch_shutdown(chip->ds);
|
||||
}
|
||||
EXPORT_SYMBOL(lan9303_shutdown);
|
||||
|
||||
MODULE_AUTHOR("Juergen Borleis <kernel@pengutronix.de>");
|
||||
MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -10,3 +10,4 @@ extern const struct lan9303_phy_ops lan9303_indirect_phy_ops;
|
||||
|
||||
int lan9303_probe(struct lan9303 *chip, struct device_node *np);
|
||||
int lan9303_remove(struct lan9303 *chip);
|
||||
void lan9303_shutdown(struct lan9303 *chip);
|
||||
|
@ -67,13 +67,28 @@ static int lan9303_i2c_probe(struct i2c_client *client,
|
||||
|
||||
static int lan9303_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct lan9303_i2c *sw_dev;
|
||||
struct lan9303_i2c *sw_dev = i2c_get_clientdata(client);
|
||||
|
||||
sw_dev = i2c_get_clientdata(client);
|
||||
if (!sw_dev)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
|
||||
return lan9303_remove(&sw_dev->chip);
|
||||
lan9303_remove(&sw_dev->chip);
|
||||
|
||||
i2c_set_clientdata(client, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lan9303_i2c_shutdown(struct i2c_client *client)
|
||||
{
|
||||
struct lan9303_i2c *sw_dev = i2c_get_clientdata(client);
|
||||
|
||||
if (!sw_dev)
|
||||
return;
|
||||
|
||||
lan9303_shutdown(&sw_dev->chip);
|
||||
|
||||
i2c_set_clientdata(client, NULL);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -97,6 +112,7 @@ static struct i2c_driver lan9303_i2c_driver = {
|
||||
},
|
||||
.probe = lan9303_i2c_probe,
|
||||
.remove = lan9303_i2c_remove,
|
||||
.shutdown = lan9303_i2c_shutdown,
|
||||
.id_table = lan9303_i2c_id,
|
||||
};
|
||||
module_i2c_driver(lan9303_i2c_driver);
|
||||
|
@ -138,6 +138,20 @@ static void lan9303_mdio_remove(struct mdio_device *mdiodev)
|
||||
return;
|
||||
|
||||
lan9303_remove(&sw_dev->chip);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void lan9303_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct lan9303_mdio *sw_dev = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!sw_dev)
|
||||
return;
|
||||
|
||||
lan9303_shutdown(&sw_dev->chip);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -155,6 +169,7 @@ static struct mdio_driver lan9303_mdio_driver = {
|
||||
},
|
||||
.probe = lan9303_mdio_probe,
|
||||
.remove = lan9303_mdio_remove,
|
||||
.shutdown = lan9303_mdio_shutdown,
|
||||
};
|
||||
mdio_module_driver(lan9303_mdio_driver);
|
||||
|
||||
|
@ -2184,6 +2184,9 @@ static int gswip_remove(struct platform_device *pdev)
|
||||
struct gswip_priv *priv = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
if (!priv)
|
||||
return 0;
|
||||
|
||||
/* disable the switch */
|
||||
gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
|
||||
|
||||
@ -2197,9 +2200,23 @@ static int gswip_remove(struct platform_device *pdev)
|
||||
for (i = 0; i < priv->num_gphy_fw; i++)
|
||||
gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gswip_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct gswip_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(priv->ds);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct gswip_hw_info gswip_xrx200 = {
|
||||
.max_ports = 7,
|
||||
.cpu_port = 6,
|
||||
@ -2223,6 +2240,7 @@ MODULE_DEVICE_TABLE(of, gswip_of_match);
|
||||
static struct platform_driver gswip_driver = {
|
||||
.probe = gswip_probe,
|
||||
.remove = gswip_remove,
|
||||
.shutdown = gswip_shutdown,
|
||||
.driver = {
|
||||
.name = "gswip",
|
||||
.of_match_table = gswip_of_match,
|
||||
|
@ -94,6 +94,8 @@ static int ksz8795_spi_remove(struct spi_device *spi)
|
||||
if (dev)
|
||||
ksz_switch_remove(dev);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -101,8 +103,15 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct ksz_device *dev = spi_get_drvdata(spi);
|
||||
|
||||
if (dev && dev->dev_ops->shutdown)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->dev_ops->shutdown)
|
||||
dev->dev_ops->shutdown(dev);
|
||||
|
||||
dsa_switch_shutdown(dev->ds);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz8795_dt_ids[] = {
|
||||
|
@ -191,6 +191,18 @@ static void ksz8863_smi_remove(struct mdio_device *mdiodev)
|
||||
|
||||
if (dev)
|
||||
ksz_switch_remove(dev);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (dev)
|
||||
dsa_switch_shutdown(dev->ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz8863_dt_ids[] = {
|
||||
@ -203,6 +215,7 @@ MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
|
||||
static struct mdio_driver ksz8863_driver = {
|
||||
.probe = ksz8863_smi_probe,
|
||||
.remove = ksz8863_smi_remove,
|
||||
.shutdown = ksz8863_smi_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "ksz8863-switch",
|
||||
.of_match_table = ksz8863_dt_ids,
|
||||
|
@ -56,7 +56,10 @@ static int ksz9477_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct ksz_device *dev = i2c_get_clientdata(i2c);
|
||||
|
||||
ksz_switch_remove(dev);
|
||||
if (dev)
|
||||
ksz_switch_remove(dev);
|
||||
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -65,8 +68,15 @@ static void ksz9477_i2c_shutdown(struct i2c_client *i2c)
|
||||
{
|
||||
struct ksz_device *dev = i2c_get_clientdata(i2c);
|
||||
|
||||
if (dev && dev->dev_ops->shutdown)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->dev_ops->shutdown)
|
||||
dev->dev_ops->shutdown(dev);
|
||||
|
||||
dsa_switch_shutdown(dev->ds);
|
||||
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ksz9477_i2c_id[] = {
|
||||
|
@ -72,6 +72,8 @@ static int ksz9477_spi_remove(struct spi_device *spi)
|
||||
if (dev)
|
||||
ksz_switch_remove(dev);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -79,8 +81,10 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct ksz_device *dev = spi_get_drvdata(spi);
|
||||
|
||||
if (dev && dev->dev_ops->shutdown)
|
||||
dev->dev_ops->shutdown(dev);
|
||||
if (dev)
|
||||
dsa_switch_shutdown(dev->ds);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz9477_dt_ids[] = {
|
||||
|
@ -3286,6 +3286,9 @@ mt7530_remove(struct mdio_device *mdiodev)
|
||||
struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
int ret = 0;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
ret = regulator_disable(priv->core_pwr);
|
||||
if (ret < 0)
|
||||
dev_err(priv->dev,
|
||||
@ -3301,11 +3304,26 @@ mt7530_remove(struct mdio_device *mdiodev)
|
||||
|
||||
dsa_unregister_switch(priv->ds);
|
||||
mutex_destroy(&priv->reg_mutex);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void mt7530_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(priv->ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static struct mdio_driver mt7530_mdio_driver = {
|
||||
.probe = mt7530_probe,
|
||||
.remove = mt7530_remove,
|
||||
.shutdown = mt7530_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "mt7530",
|
||||
.of_match_table = mt7530_of_match,
|
||||
|
@ -290,7 +290,24 @@ static void mv88e6060_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
dsa_unregister_switch(ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void mv88e6060_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id mv88e6060_of_match[] = {
|
||||
@ -303,6 +320,7 @@ static const struct of_device_id mv88e6060_of_match[] = {
|
||||
static struct mdio_driver mv88e6060_driver = {
|
||||
.probe = mv88e6060_probe,
|
||||
.remove = mv88e6060_remove,
|
||||
.shutdown = mv88e6060_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "mv88e6060",
|
||||
.of_match_table = mv88e6060_of_match,
|
||||
|
@ -3071,7 +3071,7 @@ static void mv88e6xxx_teardown(struct dsa_switch *ds)
|
||||
{
|
||||
mv88e6xxx_teardown_devlink_params(ds);
|
||||
dsa_devlink_resources_unregister(ds);
|
||||
mv88e6xxx_teardown_devlink_regions(ds);
|
||||
mv88e6xxx_teardown_devlink_regions_global(ds);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_setup(struct dsa_switch *ds)
|
||||
@ -3215,7 +3215,7 @@ unlock:
|
||||
if (err)
|
||||
goto out_resources;
|
||||
|
||||
err = mv88e6xxx_setup_devlink_regions(ds);
|
||||
err = mv88e6xxx_setup_devlink_regions_global(ds);
|
||||
if (err)
|
||||
goto out_params;
|
||||
|
||||
@ -3229,6 +3229,16 @@ out_resources:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port)
|
||||
{
|
||||
return mv88e6xxx_setup_devlink_regions_port(ds, port);
|
||||
}
|
||||
|
||||
static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port)
|
||||
{
|
||||
mv88e6xxx_teardown_devlink_regions_port(ds, port);
|
||||
}
|
||||
|
||||
/* prod_id for switch families which do not have a PHY model number */
|
||||
static const u16 family_prod_id_table[] = {
|
||||
[MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
|
||||
@ -6116,6 +6126,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
|
||||
.change_tag_protocol = mv88e6xxx_change_tag_protocol,
|
||||
.setup = mv88e6xxx_setup,
|
||||
.teardown = mv88e6xxx_teardown,
|
||||
.port_setup = mv88e6xxx_port_setup,
|
||||
.port_teardown = mv88e6xxx_port_teardown,
|
||||
.phylink_validate = mv88e6xxx_validate,
|
||||
.phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
|
||||
.phylink_mac_config = mv88e6xxx_mac_config,
|
||||
@ -6389,7 +6401,12 @@ out:
|
||||
static void mv88e6xxx_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct mv88e6xxx_chip *chip;
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
chip = ds->priv;
|
||||
|
||||
if (chip->info->ptp_support) {
|
||||
mv88e6xxx_hwtstamp_free(chip);
|
||||
@ -6410,6 +6427,20 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
|
||||
mv88e6xxx_g1_irq_free(chip);
|
||||
else
|
||||
mv88e6xxx_irq_poll_free(chip);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void mv88e6xxx_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!ds)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id mv88e6xxx_of_match[] = {
|
||||
@ -6433,6 +6464,7 @@ MODULE_DEVICE_TABLE(of, mv88e6xxx_of_match);
|
||||
static struct mdio_driver mv88e6xxx_driver = {
|
||||
.probe = mv88e6xxx_probe,
|
||||
.remove = mv88e6xxx_remove,
|
||||
.shutdown = mv88e6xxx_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "mv88e6085",
|
||||
.of_match_table = mv88e6xxx_of_match,
|
||||
|
@ -647,26 +647,25 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static void
|
||||
mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip)
|
||||
void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++)
|
||||
dsa_devlink_region_destroy(chip->regions[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip,
|
||||
int port)
|
||||
void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
|
||||
dsa_devlink_region_destroy(chip->ports[port].region);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,
|
||||
struct mv88e6xxx_chip *chip,
|
||||
int port)
|
||||
int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct devlink_region *region;
|
||||
|
||||
region = dsa_devlink_port_region_create(ds,
|
||||
@ -681,40 +680,10 @@ static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mv88e6xxx_teardown_devlink_regions_ports(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
int port;
|
||||
|
||||
for (port = 0; port < mv88e6xxx_num_ports(chip); port++)
|
||||
mv88e6xxx_teardown_devlink_regions_port(chip, port);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_setup_devlink_regions_ports(struct dsa_switch *ds,
|
||||
struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
int port;
|
||||
int err;
|
||||
|
||||
for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
|
||||
err = mv88e6xxx_setup_devlink_regions_port(ds, chip, port);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
while (port-- > 0)
|
||||
mv88e6xxx_teardown_devlink_regions_port(chip, port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds,
|
||||
struct mv88e6xxx_chip *chip)
|
||||
int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds)
|
||||
{
|
||||
bool (*cond)(struct mv88e6xxx_chip *chip);
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
struct devlink_region_ops *ops;
|
||||
struct devlink_region *region;
|
||||
u64 size;
|
||||
@ -753,30 +722,6 @@ out:
|
||||
return PTR_ERR(region);
|
||||
}
|
||||
|
||||
int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_setup_devlink_regions_global(ds, chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mv88e6xxx_setup_devlink_regions_ports(ds, chip);
|
||||
if (err)
|
||||
mv88e6xxx_teardown_devlink_regions_global(chip);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
|
||||
mv88e6xxx_teardown_devlink_regions_ports(chip);
|
||||
mv88e6xxx_teardown_devlink_regions_global(chip);
|
||||
}
|
||||
|
||||
int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,
|
||||
struct devlink_info_req *req,
|
||||
struct netlink_ext_ack *extack)
|
||||
|
@ -12,8 +12,10 @@ int mv88e6xxx_devlink_param_get(struct dsa_switch *ds, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx);
|
||||
int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx);
|
||||
int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds);
|
||||
void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds);
|
||||
int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds);
|
||||
void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds);
|
||||
int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port);
|
||||
void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port);
|
||||
|
||||
int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,
|
||||
struct devlink_info_req *req,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2019-2021 NXP Semiconductors
|
||||
/* Copyright 2019-2021 NXP
|
||||
*
|
||||
* This is an umbrella module for all network switches that are
|
||||
* register-compatible with Ocelot and that perform I/O to their host CPU
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright 2019 NXP Semiconductors
|
||||
/* Copyright 2019 NXP
|
||||
*/
|
||||
#ifndef _MSCC_FELIX_H
|
||||
#define _MSCC_FELIX_H
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/* Copyright 2017 Microsemi Corporation
|
||||
* Copyright 2018-2019 NXP Semiconductors
|
||||
* Copyright 2018-2019 NXP
|
||||
*/
|
||||
#include <linux/fsl/enetc_mdio.h>
|
||||
#include <soc/mscc/ocelot_qsys.h>
|
||||
@ -1472,9 +1472,10 @@ err_pci_enable:
|
||||
|
||||
static void felix_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct felix *felix;
|
||||
struct felix *felix = pci_get_drvdata(pdev);
|
||||
|
||||
felix = pci_get_drvdata(pdev);
|
||||
if (!felix)
|
||||
return;
|
||||
|
||||
dsa_unregister_switch(felix->ds);
|
||||
|
||||
@ -1482,6 +1483,20 @@ static void felix_pci_remove(struct pci_dev *pdev)
|
||||
kfree(felix);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static void felix_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct felix *felix = pci_get_drvdata(pdev);
|
||||
|
||||
if (!felix)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(felix->ds);
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static struct pci_device_id felix_ids[] = {
|
||||
@ -1498,6 +1513,7 @@ static struct pci_driver felix_vsc9959_pci_driver = {
|
||||
.id_table = felix_ids,
|
||||
.probe = felix_pci_probe,
|
||||
.remove = felix_pci_remove,
|
||||
.shutdown = felix_pci_shutdown,
|
||||
};
|
||||
module_pci_driver(felix_vsc9959_pci_driver);
|
||||
|
||||
|
@ -1245,18 +1245,33 @@ err_alloc_felix:
|
||||
|
||||
static int seville_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct felix *felix;
|
||||
struct felix *felix = platform_get_drvdata(pdev);
|
||||
|
||||
felix = platform_get_drvdata(pdev);
|
||||
if (!felix)
|
||||
return 0;
|
||||
|
||||
dsa_unregister_switch(felix->ds);
|
||||
|
||||
kfree(felix->ds);
|
||||
kfree(felix);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void seville_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct felix *felix = platform_get_drvdata(pdev);
|
||||
|
||||
if (!felix)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(felix->ds);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id seville_of_match[] = {
|
||||
{ .compatible = "mscc,vsc9953-switch" },
|
||||
{ },
|
||||
@ -1266,6 +1281,7 @@ MODULE_DEVICE_TABLE(of, seville_of_match);
|
||||
static struct platform_driver seville_vsc9953_driver = {
|
||||
.probe = seville_probe,
|
||||
.remove = seville_remove,
|
||||
.shutdown = seville_shutdown,
|
||||
.driver = {
|
||||
.name = "mscc_seville",
|
||||
.of_match_table = of_match_ptr(seville_of_match),
|
||||
|
@ -1083,6 +1083,9 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev)
|
||||
struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
unsigned int i;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->port); i++) {
|
||||
struct ar9331_sw_port *port = &priv->port[i];
|
||||
|
||||
@ -1094,6 +1097,20 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev)
|
||||
dsa_unregister_switch(&priv->ds);
|
||||
|
||||
reset_control_assert(priv->sw_reset);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void ar9331_sw_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct ar9331_sw_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(&priv->ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id ar9331_sw_of_match[] = {
|
||||
@ -1104,6 +1121,7 @@ static const struct of_device_id ar9331_sw_of_match[] = {
|
||||
static struct mdio_driver ar9331_sw_mdio_driver = {
|
||||
.probe = ar9331_sw_probe,
|
||||
.remove = ar9331_sw_remove,
|
||||
.shutdown = ar9331_sw_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = AR9331_SW_NAME,
|
||||
.of_match_table = ar9331_sw_of_match,
|
||||
|
@ -1880,10 +1880,27 @@ qca8k_sw_remove(struct mdio_device *mdiodev)
|
||||
struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
int i;
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
qca8k_port_set_status(priv, i, 0);
|
||||
|
||||
dsa_unregister_switch(priv->ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void qca8k_sw_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct qca8k_priv *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(priv->ds);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -1940,6 +1957,7 @@ static const struct of_device_id qca8k_of_match[] = {
|
||||
static struct mdio_driver qca8kmdio_driver = {
|
||||
.probe = qca8k_sw_probe,
|
||||
.remove = qca8k_sw_remove,
|
||||
.shutdown = qca8k_sw_shutdown,
|
||||
.mdiodrv.driver = {
|
||||
.name = "qca8k",
|
||||
.of_match_table = qca8k_of_match,
|
||||
|
@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
|
||||
smi->slave_mii_bus->parent = smi->dev;
|
||||
smi->ds->slave_mii_bus = smi->slave_mii_bus;
|
||||
|
||||
ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np);
|
||||
ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np);
|
||||
if (ret) {
|
||||
dev_err(smi->dev, "unable to register MDIO bus %s\n",
|
||||
smi->slave_mii_bus->id);
|
||||
@ -464,16 +464,33 @@ static int realtek_smi_probe(struct platform_device *pdev)
|
||||
|
||||
static int realtek_smi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
|
||||
struct realtek_smi *smi = platform_get_drvdata(pdev);
|
||||
|
||||
if (!smi)
|
||||
return 0;
|
||||
|
||||
dsa_unregister_switch(smi->ds);
|
||||
if (smi->slave_mii_bus)
|
||||
of_node_put(smi->slave_mii_bus->dev.of_node);
|
||||
gpiod_set_value(smi->reset, 1);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void realtek_smi_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct realtek_smi *smi = platform_get_drvdata(pdev);
|
||||
|
||||
if (!smi)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(smi->ds);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id realtek_smi_of_match[] = {
|
||||
{
|
||||
.compatible = "realtek,rtl8366rb",
|
||||
@ -495,6 +512,7 @@ static struct platform_driver realtek_smi_driver = {
|
||||
},
|
||||
.probe = realtek_smi_probe,
|
||||
.remove = realtek_smi_remove,
|
||||
.shutdown = realtek_smi_shutdown,
|
||||
};
|
||||
module_platform_driver(realtek_smi_driver);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
/* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
#include <linux/packing.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
* Copyright 2020 NXP Semiconductors
|
||||
* Copyright 2020 NXP
|
||||
*/
|
||||
#include "sja1105.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2020, NXP Semiconductors
|
||||
/* Copyright 2020 NXP
|
||||
*/
|
||||
#include "sja1105.h"
|
||||
#include "sja1105_vl.h"
|
||||
|
@ -3335,13 +3335,29 @@ static int sja1105_probe(struct spi_device *spi)
|
||||
static int sja1105_remove(struct spi_device *spi)
|
||||
{
|
||||
struct sja1105_private *priv = spi_get_drvdata(spi);
|
||||
struct dsa_switch *ds = priv->ds;
|
||||
|
||||
dsa_unregister_switch(ds);
|
||||
if (!priv)
|
||||
return 0;
|
||||
|
||||
dsa_unregister_switch(priv->ds);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sja1105_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct sja1105_private *priv = spi_get_drvdata(spi);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
dsa_switch_shutdown(priv->ds);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id sja1105_dt_ids[] = {
|
||||
{ .compatible = "nxp,sja1105e", .data = &sja1105e_info },
|
||||
{ .compatible = "nxp,sja1105t", .data = &sja1105t_info },
|
||||
@ -3365,6 +3381,7 @@ static struct spi_driver sja1105_driver = {
|
||||
},
|
||||
.probe = sja1105_probe,
|
||||
.remove = sja1105_remove,
|
||||
.shutdown = sja1105_shutdown,
|
||||
};
|
||||
|
||||
module_spi_driver(sja1105_driver);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2021, NXP Semiconductors
|
||||
/* Copyright 2021 NXP
|
||||
*/
|
||||
#include <linux/pcs/pcs-xpcs.h>
|
||||
#include <linux/of_mdio.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
/* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018, Sensor-Technik Wiedemann GmbH
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
/* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
#include "sja1105_static_config.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
/* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
#ifndef _SJA1105_STATIC_CONFIG_H
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2020, NXP Semiconductors
|
||||
/* Copyright 2020 NXP
|
||||
*/
|
||||
#include <net/tc_act/tc_gate.h>
|
||||
#include <linux/dsa/8021q.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright 2020, NXP Semiconductors
|
||||
/* Copyright 2020 NXP
|
||||
*/
|
||||
#ifndef _SJA1105_VL_H
|
||||
#define _SJA1105_VL_H
|
||||
|
@ -1225,6 +1225,12 @@ int vsc73xx_remove(struct vsc73xx *vsc)
|
||||
}
|
||||
EXPORT_SYMBOL(vsc73xx_remove);
|
||||
|
||||
void vsc73xx_shutdown(struct vsc73xx *vsc)
|
||||
{
|
||||
dsa_switch_shutdown(vsc->ds);
|
||||
}
|
||||
EXPORT_SYMBOL(vsc73xx_shutdown);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -116,7 +116,26 @@ static int vsc73xx_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev);
|
||||
|
||||
return vsc73xx_remove(&vsc_platform->vsc);
|
||||
if (!vsc_platform)
|
||||
return 0;
|
||||
|
||||
vsc73xx_remove(&vsc_platform->vsc);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vsc73xx_platform_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct vsc73xx_platform *vsc_platform = platform_get_drvdata(pdev);
|
||||
|
||||
if (!vsc_platform)
|
||||
return;
|
||||
|
||||
vsc73xx_shutdown(&vsc_platform->vsc);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static const struct vsc73xx_ops vsc73xx_platform_ops = {
|
||||
@ -144,6 +163,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match);
|
||||
static struct platform_driver vsc73xx_platform_driver = {
|
||||
.probe = vsc73xx_platform_probe,
|
||||
.remove = vsc73xx_platform_remove,
|
||||
.shutdown = vsc73xx_platform_shutdown,
|
||||
.driver = {
|
||||
.name = "vsc73xx-platform",
|
||||
.of_match_table = vsc73xx_of_match,
|
||||
|
@ -163,7 +163,26 @@ static int vsc73xx_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi);
|
||||
|
||||
return vsc73xx_remove(&vsc_spi->vsc);
|
||||
if (!vsc_spi)
|
||||
return 0;
|
||||
|
||||
vsc73xx_remove(&vsc_spi->vsc);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vsc73xx_spi_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi);
|
||||
|
||||
if (!vsc_spi)
|
||||
return;
|
||||
|
||||
vsc73xx_shutdown(&vsc_spi->vsc);
|
||||
|
||||
spi_set_drvdata(spi, NULL);
|
||||
}
|
||||
|
||||
static const struct vsc73xx_ops vsc73xx_spi_ops = {
|
||||
@ -191,6 +210,7 @@ MODULE_DEVICE_TABLE(of, vsc73xx_of_match);
|
||||
static struct spi_driver vsc73xx_spi_driver = {
|
||||
.probe = vsc73xx_spi_probe,
|
||||
.remove = vsc73xx_spi_remove,
|
||||
.shutdown = vsc73xx_spi_shutdown,
|
||||
.driver = {
|
||||
.name = "vsc73xx-spi",
|
||||
.of_match_table = vsc73xx_of_match,
|
||||
|
@ -27,3 +27,4 @@ struct vsc73xx_ops {
|
||||
int vsc73xx_is_addr_valid(u8 block, u8 subblock);
|
||||
int vsc73xx_probe(struct vsc73xx *vsc);
|
||||
int vsc73xx_remove(struct vsc73xx *vsc);
|
||||
void vsc73xx_shutdown(struct vsc73xx *vsc);
|
||||
|
@ -822,6 +822,12 @@ void xrs700x_switch_remove(struct xrs700x *priv)
|
||||
}
|
||||
EXPORT_SYMBOL(xrs700x_switch_remove);
|
||||
|
||||
void xrs700x_switch_shutdown(struct xrs700x *priv)
|
||||
{
|
||||
dsa_switch_shutdown(priv->ds);
|
||||
}
|
||||
EXPORT_SYMBOL(xrs700x_switch_shutdown);
|
||||
|
||||
MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>");
|
||||
MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -40,3 +40,4 @@ struct xrs700x {
|
||||
struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv);
|
||||
int xrs700x_switch_register(struct xrs700x *priv);
|
||||
void xrs700x_switch_remove(struct xrs700x *priv);
|
||||
void xrs700x_switch_shutdown(struct xrs700x *priv);
|
||||
|
@ -109,11 +109,28 @@ static int xrs700x_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct xrs700x *priv = i2c_get_clientdata(i2c);
|
||||
|
||||
if (!priv)
|
||||
return 0;
|
||||
|
||||
xrs700x_switch_remove(priv);
|
||||
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xrs700x_i2c_shutdown(struct i2c_client *i2c)
|
||||
{
|
||||
struct xrs700x *priv = i2c_get_clientdata(i2c);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
xrs700x_switch_shutdown(priv);
|
||||
|
||||
i2c_set_clientdata(i2c, NULL);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id xrs700x_i2c_id[] = {
|
||||
{ "xrs700x-switch", 0 },
|
||||
{},
|
||||
@ -137,6 +154,7 @@ static struct i2c_driver xrs700x_i2c_driver = {
|
||||
},
|
||||
.probe = xrs700x_i2c_probe,
|
||||
.remove = xrs700x_i2c_remove,
|
||||
.shutdown = xrs700x_i2c_shutdown,
|
||||
.id_table = xrs700x_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,24 @@ static void xrs700x_mdio_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
xrs700x_switch_remove(priv);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev)
|
||||
{
|
||||
struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
xrs700x_switch_shutdown(priv);
|
||||
|
||||
dev_set_drvdata(&mdiodev->dev, NULL);
|
||||
}
|
||||
|
||||
static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = {
|
||||
@ -155,6 +172,7 @@ static struct mdio_driver xrs700x_mdio_driver = {
|
||||
},
|
||||
.probe = xrs700x_mdio_probe,
|
||||
.remove = xrs700x_mdio_remove,
|
||||
.shutdown = xrs700x_mdio_shutdown,
|
||||
};
|
||||
|
||||
mdio_module_driver(xrs700x_mdio_driver);
|
||||
|
@ -413,13 +413,13 @@ static int atl_resume_common(struct device *dev, bool deep)
|
||||
if (deep) {
|
||||
/* Reinitialize Nic/Vecs objects */
|
||||
aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol);
|
||||
|
||||
ret = aq_nic_init(nic);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
if (netif_running(nic->ndev)) {
|
||||
ret = aq_nic_init(nic);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
|
||||
ret = aq_nic_start(nic);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
|
@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_device *core)
|
||||
bcma_set_drvdata(core, bgmac);
|
||||
|
||||
err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr);
|
||||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
/* If no MAC address assigned via device tree, check SPROM */
|
||||
if (err) {
|
||||
|
@ -391,7 +391,7 @@ static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp,
|
||||
* netif_tx_queue_stopped().
|
||||
*/
|
||||
smp_mb();
|
||||
if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) {
|
||||
if (bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh) {
|
||||
netif_tx_wake_queue(txq);
|
||||
return false;
|
||||
}
|
||||
@ -764,7 +764,7 @@ next_tx_int:
|
||||
smp_mb();
|
||||
|
||||
if (unlikely(netif_tx_queue_stopped(txq)) &&
|
||||
bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
|
||||
bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh &&
|
||||
READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING)
|
||||
netif_tx_wake_queue(txq);
|
||||
}
|
||||
@ -2416,7 +2416,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
|
||||
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
|
||||
tx_pkts++;
|
||||
/* return full budget so NAPI will complete. */
|
||||
if (unlikely(tx_pkts > bp->tx_wake_thresh)) {
|
||||
if (unlikely(tx_pkts >= bp->tx_wake_thresh)) {
|
||||
rx_pkts = budget;
|
||||
raw_cons = NEXT_RAW_CMP(raw_cons);
|
||||
if (budget)
|
||||
@ -3640,7 +3640,7 @@ static int bnxt_init_tx_rings(struct bnxt *bp)
|
||||
u16 i;
|
||||
|
||||
bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2,
|
||||
MAX_SKB_FRAGS + 1);
|
||||
BNXT_MIN_TX_DESC_CNT);
|
||||
|
||||
for (i = 0; i < bp->tx_nr_rings; i++) {
|
||||
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
|
||||
|
@ -629,6 +629,11 @@ struct nqe_cn {
|
||||
#define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1)
|
||||
#define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1)
|
||||
|
||||
/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra
|
||||
* BD because the first TX BD is always a long BD.
|
||||
*/
|
||||
#define BNXT_MIN_TX_DESC_CNT (MAX_SKB_FRAGS + 2)
|
||||
|
||||
#define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
|
||||
#define RX_IDX(x) ((x) & (RX_DESC_CNT - 1))
|
||||
|
||||
|
@ -798,7 +798,7 @@ static int bnxt_set_ringparam(struct net_device *dev,
|
||||
|
||||
if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) ||
|
||||
(ering->tx_pending > BNXT_MAX_TX_DESC_CNT) ||
|
||||
(ering->tx_pending <= MAX_SKB_FRAGS))
|
||||
(ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev))
|
||||
|
@ -419,7 +419,7 @@ static void enetc_rx_dim_work(struct work_struct *w)
|
||||
|
||||
static void enetc_rx_net_dim(struct enetc_int_vector *v)
|
||||
{
|
||||
struct dim_sample dim_sample;
|
||||
struct dim_sample dim_sample = {};
|
||||
|
||||
v->comp_cnt++;
|
||||
|
||||
@ -1879,7 +1879,6 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv)
|
||||
static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
|
||||
{
|
||||
struct pci_dev *pdev = priv->si->pdev;
|
||||
cpumask_t cpu_mask;
|
||||
int i, j, err;
|
||||
|
||||
for (i = 0; i < priv->bdr_int_num; i++) {
|
||||
@ -1908,9 +1907,7 @@ static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
|
||||
|
||||
enetc_wr(hw, ENETC_SIMSITRV(idx), entry);
|
||||
}
|
||||
cpumask_clear(&cpu_mask);
|
||||
cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
|
||||
irq_set_affinity_hint(irq, &cpu_mask);
|
||||
irq_set_affinity_hint(irq, get_cpu_mask(i % num_online_cpus()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
|
||||
/* Copyright 2021 NXP Semiconductors
|
||||
/* Copyright 2021 NXP
|
||||
*
|
||||
* The Integrated Endpoint Register Block (IERB) is configured by pre-boot
|
||||
* software and is supposed to be to ENETC what a NVRAM is to a 'real' PCIe
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
|
||||
/* Copyright 2021 NXP Semiconductors */
|
||||
/* Copyright 2021 NXP */
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -4176,5 +4176,4 @@ static struct platform_driver fec_driver = {
|
||||
|
||||
module_platform_driver(fec_driver);
|
||||
|
||||
MODULE_ALIAS("platform:"DRIVER_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -2445,12 +2445,12 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev,
|
||||
return;
|
||||
}
|
||||
|
||||
dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vf_id(%u), queue_id(%u)\n",
|
||||
dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vport(%u), queue_id(%u)\n",
|
||||
vf_id, q_id);
|
||||
|
||||
if (vf_id) {
|
||||
if (vf_id >= hdev->num_alloc_vport) {
|
||||
dev_err(dev, "invalid vf id(%u)\n", vf_id);
|
||||
dev_err(dev, "invalid vport(%u)\n", vf_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2463,8 +2463,8 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev,
|
||||
|
||||
ret = hclge_inform_reset_assert_to_vf(&hdev->vport[vf_id]);
|
||||
if (ret)
|
||||
dev_err(dev, "inform reset to vf(%u) failed %d!\n",
|
||||
hdev->vport->vport_id, ret);
|
||||
dev_err(dev, "inform reset to vport(%u) failed %d!\n",
|
||||
vf_id, ret);
|
||||
} else {
|
||||
set_bit(HNAE3_FUNC_RESET, reset_requests);
|
||||
}
|
||||
|
@ -3661,7 +3661,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"set vf(%u) rst failed %d!\n",
|
||||
vport->vport_id, ret);
|
||||
vport->vport_id - HCLGE_VF_VPORT_START_NUM,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3676,7 +3677,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
|
||||
if (ret)
|
||||
dev_warn(&hdev->pdev->dev,
|
||||
"inform reset to vf(%u) failed %d!\n",
|
||||
vport->vport_id, ret);
|
||||
vport->vport_id - HCLGE_VF_VPORT_START_NUM,
|
||||
ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -4741,6 +4743,24 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_parse_rss_hfunc(struct hclge_vport *vport, const u8 hfunc,
|
||||
u8 *hash_algo)
|
||||
{
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
*hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
|
||||
return 0;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
*hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
|
||||
return 0;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
*hash_algo = vport->rss_algo;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
@ -4750,30 +4770,27 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
||||
u8 hash_algo;
|
||||
int ret, i;
|
||||
|
||||
ret = hclge_parse_rss_hfunc(vport, hfunc, &hash_algo);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "invalid hfunc type %u\n", hfunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the RSS Hash Key if specififed by the user */
|
||||
if (key) {
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
|
||||
break;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
|
||||
break;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
hash_algo = vport->rss_algo;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = hclge_set_rss_algo_key(hdev, hash_algo, key);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update the shadow RSS key with user specified qids */
|
||||
memcpy(vport->rss_hash_key, key, HCLGE_RSS_KEY_SIZE);
|
||||
vport->rss_algo = hash_algo;
|
||||
} else {
|
||||
ret = hclge_set_rss_algo_key(hdev, hash_algo,
|
||||
vport->rss_hash_key);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
vport->rss_algo = hash_algo;
|
||||
|
||||
/* Update the shadow RSS table with user specified qids */
|
||||
for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++)
|
||||
@ -6627,10 +6644,13 @@ static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie,
|
||||
u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
|
||||
u16 tqps;
|
||||
|
||||
/* To keep consistent with user's configuration, minus 1 when
|
||||
* printing 'vf', because vf id from ethtool is added 1 for vf.
|
||||
*/
|
||||
if (vf > hdev->num_req_vfs) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"Error: vf id (%u) > max vf num (%u)\n",
|
||||
vf, hdev->num_req_vfs);
|
||||
"Error: vf id (%u) should be less than %u\n",
|
||||
vf - 1, hdev->num_req_vfs);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -9797,6 +9817,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
|
||||
if (is_kill && !vlan_id)
|
||||
return 0;
|
||||
|
||||
if (vlan_id >= VLAN_N_VID)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
@ -10703,7 +10726,8 @@ static int hclge_reset_tqp_cmd_send(struct hclge_dev *hdev, u16 queue_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
|
||||
static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id,
|
||||
u8 *reset_status)
|
||||
{
|
||||
struct hclge_reset_tqp_queue_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
@ -10721,7 +10745,9 @@ static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B);
|
||||
*reset_status = hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id)
|
||||
@ -10740,7 +10766,7 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle)
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
u16 reset_try_times = 0;
|
||||
int reset_status;
|
||||
u8 reset_status;
|
||||
u16 queue_gid;
|
||||
int ret;
|
||||
u16 i;
|
||||
@ -10756,7 +10782,11 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle)
|
||||
}
|
||||
|
||||
while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) {
|
||||
reset_status = hclge_get_reset_status(hdev, queue_gid);
|
||||
ret = hclge_get_reset_status(hdev, queue_gid,
|
||||
&reset_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (reset_status)
|
||||
break;
|
||||
|
||||
@ -11449,11 +11479,11 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev)
|
||||
struct hclge_vport *vport = &hdev->vport[i];
|
||||
int ret;
|
||||
|
||||
/* Send cmd to clear VF's FUNC_RST_ING */
|
||||
/* Send cmd to clear vport's FUNC_RST_ING */
|
||||
ret = hclge_set_vf_rst(hdev, vport->vport_id, false);
|
||||
if (ret)
|
||||
dev_warn(&hdev->pdev->dev,
|
||||
"clear vf(%u) rst failed %d!\n",
|
||||
"clear vport(%u) rst failed %d!\n",
|
||||
vport->vport_id, ret);
|
||||
}
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ static int hclge_reset_vf(struct hclge_vport *vport)
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
|
||||
dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!",
|
||||
vport->vport_id);
|
||||
vport->vport_id - HCLGE_VF_VPORT_START_NUM);
|
||||
|
||||
return hclge_func_reset_cmd(hdev, vport->vport_id);
|
||||
}
|
||||
@ -590,9 +590,17 @@ static void hclge_get_queue_id_in_pf(struct hclge_vport *vport,
|
||||
struct hclge_mbx_vf_to_pf_cmd *mbx_req,
|
||||
struct hclge_respond_to_vf_msg *resp_msg)
|
||||
{
|
||||
struct hnae3_handle *handle = &vport->nic;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
u16 queue_id, qid_in_pf;
|
||||
|
||||
memcpy(&queue_id, mbx_req->msg.data, sizeof(queue_id));
|
||||
if (queue_id >= handle->kinfo.num_tqps) {
|
||||
dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n",
|
||||
queue_id, mbx_req->mbx_src_vfid);
|
||||
return;
|
||||
}
|
||||
|
||||
qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id);
|
||||
memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf));
|
||||
resp_msg->len = sizeof(qid_in_pf);
|
||||
|
@ -581,7 +581,7 @@ int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate)
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"vf%u, qs%u failed to set tx_rate:%d, ret=%d\n",
|
||||
"vport%u, qs%u failed to set tx_rate:%d, ret=%d\n",
|
||||
vport->vport_id, shap_cfg_cmd->qs_id,
|
||||
max_tx_rate, ret);
|
||||
return ret;
|
||||
|
@ -816,40 +816,56 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclgevf_parse_rss_hfunc(struct hclgevf_dev *hdev, const u8 hfunc,
|
||||
u8 *hash_algo)
|
||||
{
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
*hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
|
||||
return 0;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
*hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
|
||||
return 0;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
*hash_algo = hdev->rss_cfg.hash_algo;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
||||
struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
|
||||
u8 hash_algo;
|
||||
int ret, i;
|
||||
|
||||
if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
|
||||
ret = hclgevf_parse_rss_hfunc(hdev, hfunc, &hash_algo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set the RSS Hash Key if specififed by the user */
|
||||
if (key) {
|
||||
switch (hfunc) {
|
||||
case ETH_RSS_HASH_TOP:
|
||||
rss_cfg->hash_algo =
|
||||
HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
|
||||
break;
|
||||
case ETH_RSS_HASH_XOR:
|
||||
rss_cfg->hash_algo =
|
||||
HCLGEVF_RSS_HASH_ALGO_SIMPLE;
|
||||
break;
|
||||
case ETH_RSS_HASH_NO_CHANGE:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
|
||||
key);
|
||||
if (ret)
|
||||
ret = hclgevf_set_rss_algo_key(hdev, hash_algo, key);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"invalid hfunc type %u\n", hfunc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update the shadow RSS key with user specified qids */
|
||||
memcpy(rss_cfg->rss_hash_key, key,
|
||||
HCLGEVF_RSS_KEY_SIZE);
|
||||
} else {
|
||||
ret = hclgevf_set_rss_algo_key(hdev, hash_algo,
|
||||
rss_cfg->rss_hash_key);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
rss_cfg->hash_algo = hash_algo;
|
||||
}
|
||||
|
||||
/* update the shadow RSS table with user specified qids */
|
||||
|
@ -335,6 +335,7 @@ config IGC
|
||||
tristate "Intel(R) Ethernet Controller I225-LM/I225-V support"
|
||||
default n
|
||||
depends on PCI
|
||||
depends on PTP_1588_CLOCK_OPTIONAL
|
||||
help
|
||||
This driver supports Intel(R) Ethernet Controller I225-LM/I225-V
|
||||
family of adapters.
|
||||
|
@ -186,6 +186,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
|
||||
int hash;
|
||||
int i;
|
||||
|
||||
if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params))
|
||||
return -EEXIST;
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
|
||||
struct flow_match_meta match;
|
||||
|
||||
|
@ -372,6 +372,9 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
||||
int nhoff = skb_network_offset(skb);
|
||||
int ret = 0;
|
||||
|
||||
if (skb->encapsulation)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
if (skb->protocol != htons(ETH_P_IP))
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
@ -1269,7 +1272,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work)
|
||||
if (!netif_carrier_ok(dev)) {
|
||||
if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
|
||||
if (priv->port_state.link_state) {
|
||||
priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
|
||||
netif_carrier_on(dev);
|
||||
en_dbg(LINK, priv, "Link Up\n");
|
||||
}
|
||||
@ -1557,26 +1559,36 @@ static void mlx4_en_service_task(struct work_struct *work)
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
}
|
||||
|
||||
static void mlx4_en_linkstate(struct work_struct *work)
|
||||
static void mlx4_en_linkstate(struct mlx4_en_priv *priv)
|
||||
{
|
||||
struct mlx4_en_port_state *port_state = &priv->port_state;
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct net_device *dev = priv->dev;
|
||||
bool up;
|
||||
|
||||
if (mlx4_en_QUERY_PORT(mdev, priv->port))
|
||||
port_state->link_state = MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN;
|
||||
|
||||
up = port_state->link_state == MLX4_PORT_STATE_DEV_EVENT_PORT_UP;
|
||||
if (up == netif_carrier_ok(dev))
|
||||
netif_carrier_event(dev);
|
||||
if (!up) {
|
||||
en_info(priv, "Link Down\n");
|
||||
netif_carrier_off(dev);
|
||||
} else {
|
||||
en_info(priv, "Link Up\n");
|
||||
netif_carrier_on(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlx4_en_linkstate_work(struct work_struct *work)
|
||||
{
|
||||
struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
|
||||
linkstate_task);
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
int linkstate = priv->link_state;
|
||||
|
||||
mutex_lock(&mdev->state_lock);
|
||||
/* If observable port state changed set carrier state and
|
||||
* report to system log */
|
||||
if (priv->last_link_state != linkstate) {
|
||||
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
|
||||
en_info(priv, "Link Down\n");
|
||||
netif_carrier_off(priv->dev);
|
||||
} else {
|
||||
en_info(priv, "Link Up\n");
|
||||
netif_carrier_on(priv->dev);
|
||||
}
|
||||
}
|
||||
priv->last_link_state = linkstate;
|
||||
mlx4_en_linkstate(priv);
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
}
|
||||
|
||||
@ -2079,9 +2091,11 @@ static int mlx4_en_open(struct net_device *dev)
|
||||
mlx4_en_clear_stats(dev);
|
||||
|
||||
err = mlx4_en_start_port(dev);
|
||||
if (err)
|
||||
if (err) {
|
||||
en_err(priv, "Failed starting port:%d\n", priv->port);
|
||||
|
||||
goto out;
|
||||
}
|
||||
mlx4_en_linkstate(priv);
|
||||
out:
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
return err;
|
||||
@ -3168,7 +3182,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||
spin_lock_init(&priv->stats_lock);
|
||||
INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
|
||||
INIT_WORK(&priv->restart_task, mlx4_en_restart);
|
||||
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
|
||||
INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate_work);
|
||||
INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
|
||||
INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
|
@ -552,7 +552,6 @@ struct mlx4_en_priv {
|
||||
|
||||
struct mlx4_hwq_resources res;
|
||||
int link_state;
|
||||
int last_link_state;
|
||||
bool port_up;
|
||||
int port;
|
||||
int registered;
|
||||
|
@ -563,16 +563,6 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
|
||||
ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
|
||||
DEV_MAC_ENA_CFG_TX_ENA, DEV_MAC_ENA_CFG);
|
||||
|
||||
/* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
|
||||
* reset
|
||||
*/
|
||||
ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
|
||||
DEV_CLOCK_CFG);
|
||||
|
||||
/* No PFC */
|
||||
ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
|
||||
ANA_PFC_PFC_CFG, port);
|
||||
|
||||
/* Core: Enable port for frame transfer */
|
||||
ocelot_fields_write(ocelot, port,
|
||||
QSYS_SWITCH_PORT_MODE_PORT_ENA, 1);
|
||||
@ -1303,14 +1293,19 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond,
|
||||
return mask;
|
||||
}
|
||||
|
||||
static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot,
|
||||
static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, int src_port,
|
||||
struct net_device *bridge)
|
||||
{
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[src_port];
|
||||
u32 mask = 0;
|
||||
int port;
|
||||
|
||||
if (!ocelot_port || ocelot_port->bridge != bridge ||
|
||||
ocelot_port->stp_state != BR_STATE_FORWARDING)
|
||||
return 0;
|
||||
|
||||
for (port = 0; port < ocelot->num_phys_ports; port++) {
|
||||
struct ocelot_port *ocelot_port = ocelot->ports[port];
|
||||
ocelot_port = ocelot->ports[port];
|
||||
|
||||
if (!ocelot_port)
|
||||
continue;
|
||||
@ -1376,7 +1371,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
|
||||
struct net_device *bridge = ocelot_port->bridge;
|
||||
struct net_device *bond = ocelot_port->bond;
|
||||
|
||||
mask = ocelot_get_bridge_fwd_mask(ocelot, bridge);
|
||||
mask = ocelot_get_bridge_fwd_mask(ocelot, port, bridge);
|
||||
mask |= cpu_fwd_mask;
|
||||
mask &= ~BIT(port);
|
||||
if (bond) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/* Copyright 2020-2021 NXP Semiconductors
|
||||
/* Copyright 2020-2021 NXP
|
||||
*/
|
||||
#include <net/devlink.h>
|
||||
#include "ocelot.h"
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* Microsemi Ocelot Switch driver
|
||||
*
|
||||
* Copyright (c) 2017, 2019 Microsemi Corporation
|
||||
* Copyright 2020-2021 NXP Semiconductors
|
||||
* Copyright 2020-2021 NXP
|
||||
*/
|
||||
|
||||
#include <linux/if_bridge.h>
|
||||
|
@ -5,7 +5,7 @@
|
||||
* mscc_ocelot_switch_lib.
|
||||
*
|
||||
* Copyright (c) 2017, 2019 Microsemi Corporation
|
||||
* Copyright 2020-2021 NXP Semiconductors
|
||||
* Copyright 2020-2021 NXP
|
||||
*/
|
||||
|
||||
#include <linux/if_bridge.h>
|
||||
|
@ -1297,6 +1297,14 @@ qed_iwarp_wait_cid_map_cleared(struct qed_hwfn *p_hwfn, struct qed_bmap *bmap)
|
||||
prev_weight = weight;
|
||||
|
||||
while (weight) {
|
||||
/* If the HW device is during recovery, all resources are
|
||||
* immediately reset without receiving a per-cid indication
|
||||
* from HW. In this case we don't expect the cid_map to be
|
||||
* cleared.
|
||||
*/
|
||||
if (p_hwfn->cdev->recov_in_prog)
|
||||
return 0;
|
||||
|
||||
msleep(QED_IWARP_MAX_CID_CLEAN_TIME);
|
||||
|
||||
weight = bitmap_weight(bmap->bitmap, bmap->max_count);
|
||||
|
@ -77,6 +77,14 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn)
|
||||
* Beyond the added delay we clear the bitmap anyway.
|
||||
*/
|
||||
while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) {
|
||||
/* If the HW device is during recovery, all resources are
|
||||
* immediately reset without receiving a per-cid indication
|
||||
* from HW. In this case we don't expect the cid bitmap to be
|
||||
* cleared.
|
||||
*/
|
||||
if (p_hwfn->cdev->recov_in_prog)
|
||||
return;
|
||||
|
||||
msleep(100);
|
||||
if (wait_count++ > 20) {
|
||||
DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n");
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2021 NXP Semiconductors
|
||||
/* Copyright 2021 NXP
|
||||
*/
|
||||
#include <linux/pcs/pcs-xpcs.h>
|
||||
#include "pcs-xpcs.h"
|
||||
|
@ -179,6 +179,16 @@ static int mdio_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mdio_shutdown(struct device *dev)
|
||||
{
|
||||
struct mdio_device *mdiodev = to_mdio_device(dev);
|
||||
struct device_driver *drv = mdiodev->dev.driver;
|
||||
struct mdio_driver *mdiodrv = to_mdio_driver(drv);
|
||||
|
||||
if (mdiodrv->shutdown)
|
||||
mdiodrv->shutdown(mdiodev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mdio_driver_register - register an mdio_driver with the MDIO layer
|
||||
* @drv: new mdio_driver to register
|
||||
@ -193,6 +203,7 @@ int mdio_driver_register(struct mdio_driver *drv)
|
||||
mdiodrv->driver.bus = &mdio_bus_type;
|
||||
mdiodrv->driver.probe = mdio_probe;
|
||||
mdiodrv->driver.remove = mdio_remove;
|
||||
mdiodrv->driver.shutdown = mdio_shutdown;
|
||||
|
||||
retval = driver_register(&mdiodrv->driver);
|
||||
if (retval) {
|
||||
|
@ -2719,14 +2719,14 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface,
|
||||
|
||||
serial = kzalloc(sizeof(*serial), GFP_KERNEL);
|
||||
if (!serial)
|
||||
goto exit;
|
||||
goto err_free_dev;
|
||||
|
||||
hso_dev->port_data.dev_serial = serial;
|
||||
serial->parent = hso_dev;
|
||||
|
||||
if (hso_serial_common_create
|
||||
(serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE))
|
||||
goto exit;
|
||||
goto err_free_serial;
|
||||
|
||||
serial->tx_data_length--;
|
||||
serial->write_data = hso_mux_serial_write_data;
|
||||
@ -2742,11 +2742,9 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface,
|
||||
/* done, return it */
|
||||
return hso_dev;
|
||||
|
||||
exit:
|
||||
if (serial) {
|
||||
tty_unregister_device(tty_drv, serial->minor);
|
||||
kfree(serial);
|
||||
}
|
||||
err_free_serial:
|
||||
kfree(serial);
|
||||
err_free_dev:
|
||||
kfree(hso_dev);
|
||||
return NULL;
|
||||
|
||||
|
@ -423,6 +423,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
|
||||
|
||||
skb_reserve(skb, p - buf);
|
||||
skb_put(skb, len);
|
||||
|
||||
page = (struct page *)page->private;
|
||||
if (page)
|
||||
give_pages(rq, page);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
|
@ -4756,12 +4756,12 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
|
||||
LIST_HEAD(list);
|
||||
unsigned int h;
|
||||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(net, net_list, exit_list) {
|
||||
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
|
||||
|
||||
unregister_nexthop_notifier(net, &vn->nexthop_notifier_block);
|
||||
}
|
||||
rtnl_lock();
|
||||
list_for_each_entry(net, net_list, exit_list)
|
||||
vxlan_destroy_tunnels(net, &list);
|
||||
|
||||
|
@ -499,7 +499,7 @@ check_frags:
|
||||
* the header's copy failed, and they are
|
||||
* sharing a slot, send an error
|
||||
*/
|
||||
if (i == 0 && sharedslot)
|
||||
if (i == 0 && !first_shinfo && sharedslot)
|
||||
xenvif_idx_release(queue, pending_idx,
|
||||
XEN_NETIF_RSP_ERROR);
|
||||
else
|
||||
|
@ -278,6 +278,7 @@ static int st_nci_spi_remove(struct spi_device *dev)
|
||||
|
||||
static struct spi_device_id st_nci_spi_id_table[] = {
|
||||
{ST_NCI_SPI_DRIVER_NAME, 0},
|
||||
{"st21nfcb-spi", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
|
||||
|
@ -174,6 +174,7 @@ config PTP_1588_CLOCK_OCP
|
||||
depends on I2C && MTD
|
||||
depends on SERIAL_8250
|
||||
depends on !S390
|
||||
depends on COMMON_CLK
|
||||
select NET_DEVLINK
|
||||
help
|
||||
This driver adds support for an OpenCompute time card.
|
||||
|
@ -77,12 +77,13 @@ EXPORT_SYMBOL(ccwgroup_set_online);
|
||||
/**
|
||||
* ccwgroup_set_offline() - disable a ccwgroup device
|
||||
* @gdev: target ccwgroup device
|
||||
* @call_gdrv: Call the registered gdrv set_offline function
|
||||
*
|
||||
* This function attempts to put the ccwgroup device into the offline state.
|
||||
* Returns:
|
||||
* %0 on success and a negative error value on failure.
|
||||
*/
|
||||
int ccwgroup_set_offline(struct ccwgroup_device *gdev)
|
||||
int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv)
|
||||
{
|
||||
struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
|
||||
int ret = -EINVAL;
|
||||
@ -91,11 +92,16 @@ int ccwgroup_set_offline(struct ccwgroup_device *gdev)
|
||||
return -EAGAIN;
|
||||
if (gdev->state == CCWGROUP_OFFLINE)
|
||||
goto out;
|
||||
if (!call_gdrv) {
|
||||
ret = 0;
|
||||
goto offline;
|
||||
}
|
||||
if (gdrv->set_offline)
|
||||
ret = gdrv->set_offline(gdev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
offline:
|
||||
gdev->state = CCWGROUP_OFFLINE;
|
||||
out:
|
||||
atomic_set(&gdev->onoff, 0);
|
||||
@ -124,7 +130,7 @@ static ssize_t ccwgroup_online_store(struct device *dev,
|
||||
if (value == 1)
|
||||
ret = ccwgroup_set_online(gdev);
|
||||
else if (value == 0)
|
||||
ret = ccwgroup_set_offline(gdev);
|
||||
ret = ccwgroup_set_offline(gdev, true);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
out:
|
||||
|
@ -858,7 +858,6 @@ struct qeth_card {
|
||||
struct napi_struct napi;
|
||||
struct qeth_rx rx;
|
||||
struct delayed_work buffer_reclaim_work;
|
||||
struct work_struct close_dev_work;
|
||||
};
|
||||
|
||||
static inline bool qeth_card_hw_is_reachable(struct qeth_card *card)
|
||||
|
@ -70,15 +70,6 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
|
||||
static int qeth_qdio_establish(struct qeth_card *);
|
||||
static void qeth_free_qdio_queues(struct qeth_card *card);
|
||||
|
||||
static void qeth_close_dev_handler(struct work_struct *work)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
|
||||
card = container_of(work, struct qeth_card, close_dev_work);
|
||||
QETH_CARD_TEXT(card, 2, "cldevhdl");
|
||||
ccwgroup_set_offline(card->gdev);
|
||||
}
|
||||
|
||||
static const char *qeth_get_cardname(struct qeth_card *card)
|
||||
{
|
||||
if (IS_VM_NIC(card)) {
|
||||
@ -202,6 +193,9 @@ static void qeth_clear_working_pool_list(struct qeth_card *card)
|
||||
&card->qdio.in_buf_pool.entry_list, list)
|
||||
list_del(&pool_entry->list);
|
||||
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(queue->bufs); i++)
|
||||
queue->bufs[i].pool_entry = NULL;
|
||||
}
|
||||
@ -792,10 +786,12 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
||||
case IPA_CMD_STOPLAN:
|
||||
if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Interface %s is down because the adjacent port is no longer in reflective relay mode\n",
|
||||
"Adjacent port of interface %s is no longer in reflective relay mode, trigger recovery\n",
|
||||
netdev_name(card->dev));
|
||||
schedule_work(&card->close_dev_work);
|
||||
/* Set offline, then probably fail to set online: */
|
||||
qeth_schedule_recovery(card);
|
||||
} else {
|
||||
/* stay online for subsequent STARTLAN */
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The link for interface %s on CHPID 0x%X failed\n",
|
||||
netdev_name(card->dev), card->info.chpid);
|
||||
@ -1537,7 +1533,6 @@ static void qeth_setup_card(struct qeth_card *card)
|
||||
INIT_LIST_HEAD(&card->ipato.entries);
|
||||
qeth_init_qdio_info(card);
|
||||
INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work);
|
||||
INIT_WORK(&card->close_dev_work, qeth_close_dev_handler);
|
||||
hash_init(card->rx_mode_addrs);
|
||||
hash_init(card->local_addrs4);
|
||||
hash_init(card->local_addrs6);
|
||||
@ -5519,7 +5514,8 @@ static int qeth_do_reset(void *data)
|
||||
dev_info(&card->gdev->dev,
|
||||
"Device successfully recovered!\n");
|
||||
} else {
|
||||
ccwgroup_set_offline(card->gdev);
|
||||
qeth_set_offline(card, disc, true);
|
||||
ccwgroup_set_offline(card->gdev, false);
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The qeth device driver failed to recover an error on the device\n");
|
||||
}
|
||||
|
@ -2307,7 +2307,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *gdev)
|
||||
if (gdev->state == CCWGROUP_ONLINE)
|
||||
qeth_set_offline(card, card->discipline, false);
|
||||
|
||||
cancel_work_sync(&card->close_dev_work);
|
||||
if (card->dev->reg_state == NETREG_REGISTERED) {
|
||||
priv = netdev_priv(card->dev);
|
||||
if (priv->brport_features & BR_LEARNING_SYNC) {
|
||||
|
@ -1969,7 +1969,6 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
|
||||
if (cgdev->state == CCWGROUP_ONLINE)
|
||||
qeth_set_offline(card, card->discipline, false);
|
||||
|
||||
cancel_work_sync(&card->close_dev_work);
|
||||
if (card->dev->reg_state == NETREG_REGISTERED)
|
||||
unregister_netdev(card->dev);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
* Copyright 2019-2021 NXP Semiconductors
|
||||
* Copyright 2019-2021 NXP
|
||||
*/
|
||||
|
||||
#ifndef _NET_DSA_TAG_OCELOT_H
|
||||
|
@ -80,6 +80,9 @@ struct mdio_driver {
|
||||
|
||||
/* Clears up any memory if needed */
|
||||
void (*remove)(struct mdio_device *mdiodev);
|
||||
|
||||
/* Quiesces the device on system shutdown, turns off interrupts etc */
|
||||
void (*shutdown)(struct mdio_device *mdiodev);
|
||||
};
|
||||
|
||||
static inline struct mdio_driver *
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
#ifndef _LINUX_PACKING_H
|
||||
|
@ -585,8 +585,16 @@ struct dsa_switch_ops {
|
||||
int (*change_tag_protocol)(struct dsa_switch *ds, int port,
|
||||
enum dsa_tag_protocol proto);
|
||||
|
||||
/* Optional switch-wide initialization and destruction methods */
|
||||
int (*setup)(struct dsa_switch *ds);
|
||||
void (*teardown)(struct dsa_switch *ds);
|
||||
|
||||
/* Per-port initialization and destruction methods. Mandatory if the
|
||||
* driver registers devlink port regions, optional otherwise.
|
||||
*/
|
||||
int (*port_setup)(struct dsa_switch *ds, int port);
|
||||
void (*port_teardown)(struct dsa_switch *ds, int port);
|
||||
|
||||
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
|
||||
|
||||
/*
|
||||
@ -1046,6 +1054,7 @@ static inline int dsa_ndo_eth_ioctl(struct net_device *dev, struct ifreq *ifr,
|
||||
|
||||
void dsa_unregister_switch(struct dsa_switch *ds);
|
||||
int dsa_register_switch(struct dsa_switch *ds);
|
||||
void dsa_switch_shutdown(struct dsa_switch *ds);
|
||||
struct dsa_switch *dsa_switch_find(int tree_index, int sw_index);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int dsa_switch_suspend(struct dsa_switch *ds);
|
||||
|
@ -1640,6 +1640,7 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow)
|
||||
release_sock(sk);
|
||||
__release(&sk->sk_lock.slock);
|
||||
} else {
|
||||
mutex_release(&sk->sk_lock.dep_map, _RET_IP_);
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
/* Copyright (c) 2016-2018, NXP Semiconductors
|
||||
/* Copyright 2016-2018 NXP
|
||||
* Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
|
||||
*/
|
||||
#include <linux/packing.h>
|
||||
|
@ -6923,12 +6923,16 @@ EXPORT_SYMBOL(napi_disable);
|
||||
*/
|
||||
void napi_enable(struct napi_struct *n)
|
||||
{
|
||||
BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(NAPI_STATE_SCHED, &n->state);
|
||||
clear_bit(NAPI_STATE_NPSVC, &n->state);
|
||||
if (n->dev->threaded && n->thread)
|
||||
set_bit(NAPI_STATE_THREADED, &n->state);
|
||||
unsigned long val, new;
|
||||
|
||||
do {
|
||||
val = READ_ONCE(n->state);
|
||||
BUG_ON(!test_bit(NAPI_STATE_SCHED, &val));
|
||||
|
||||
new = val & ~(NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC);
|
||||
if (n->dev->threaded && n->thread)
|
||||
new |= NAPIF_STATE_THREADED;
|
||||
} while (cmpxchg(&n->state, val, new) != val);
|
||||
}
|
||||
EXPORT_SYMBOL(napi_enable);
|
||||
|
||||
|
@ -3179,17 +3179,15 @@ EXPORT_SYMBOL(sock_init_data);
|
||||
|
||||
void lock_sock_nested(struct sock *sk, int subclass)
|
||||
{
|
||||
/* The sk_lock has mutex_lock() semantics here. */
|
||||
mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
|
||||
|
||||
might_sleep();
|
||||
spin_lock_bh(&sk->sk_lock.slock);
|
||||
if (sk->sk_lock.owned)
|
||||
__lock_sock(sk);
|
||||
sk->sk_lock.owned = 1;
|
||||
spin_unlock(&sk->sk_lock.slock);
|
||||
/*
|
||||
* The sk_lock has mutex_lock() semantics here:
|
||||
*/
|
||||
mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
|
||||
local_bh_enable();
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
}
|
||||
EXPORT_SYMBOL(lock_sock_nested);
|
||||
|
||||
@ -3227,24 +3225,35 @@ EXPORT_SYMBOL(release_sock);
|
||||
*/
|
||||
bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock)
|
||||
{
|
||||
/* The sk_lock has mutex_lock() semantics here. */
|
||||
mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_);
|
||||
|
||||
might_sleep();
|
||||
spin_lock_bh(&sk->sk_lock.slock);
|
||||
|
||||
if (!sk->sk_lock.owned)
|
||||
if (!sk->sk_lock.owned) {
|
||||
/*
|
||||
* Note : We must disable BH
|
||||
* Fast path return with bottom halves disabled and
|
||||
* sock::sk_lock.slock held.
|
||||
*
|
||||
* The 'mutex' is not contended and holding
|
||||
* sock::sk_lock.slock prevents all other lockers to
|
||||
* proceed so the corresponding unlock_sock_fast() can
|
||||
* avoid the slow path of release_sock() completely and
|
||||
* just release slock.
|
||||
*
|
||||
* From a semantical POV this is equivalent to 'acquiring'
|
||||
* the 'mutex', hence the corresponding lockdep
|
||||
* mutex_release() has to happen in the fast path of
|
||||
* unlock_sock_fast().
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
__lock_sock(sk);
|
||||
sk->sk_lock.owned = 1;
|
||||
spin_unlock(&sk->sk_lock.slock);
|
||||
/*
|
||||
* The sk_lock has mutex_lock() semantics here:
|
||||
*/
|
||||
mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_);
|
||||
__acquire(&sk->sk_lock.slock);
|
||||
local_bh_enable();
|
||||
spin_unlock_bh(&sk->sk_lock.slock);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(lock_sock_fast);
|
||||
|
114
net/dsa/dsa2.c
114
net/dsa/dsa2.c
@ -429,6 +429,7 @@ static int dsa_port_setup(struct dsa_port *dp)
|
||||
{
|
||||
struct devlink_port *dlp = &dp->devlink_port;
|
||||
bool dsa_port_link_registered = false;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
bool dsa_port_enabled = false;
|
||||
int err = 0;
|
||||
|
||||
@ -438,6 +439,12 @@ static int dsa_port_setup(struct dsa_port *dp)
|
||||
INIT_LIST_HEAD(&dp->fdbs);
|
||||
INIT_LIST_HEAD(&dp->mdbs);
|
||||
|
||||
if (ds->ops->port_setup) {
|
||||
err = ds->ops->port_setup(ds, dp->index);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (dp->type) {
|
||||
case DSA_PORT_TYPE_UNUSED:
|
||||
dsa_port_disable(dp);
|
||||
@ -480,8 +487,11 @@ static int dsa_port_setup(struct dsa_port *dp)
|
||||
dsa_port_disable(dp);
|
||||
if (err && dsa_port_link_registered)
|
||||
dsa_port_link_unregister_of(dp);
|
||||
if (err)
|
||||
if (err) {
|
||||
if (ds->ops->port_teardown)
|
||||
ds->ops->port_teardown(ds, dp->index);
|
||||
return err;
|
||||
}
|
||||
|
||||
dp->setup = true;
|
||||
|
||||
@ -533,11 +543,15 @@ static int dsa_port_devlink_setup(struct dsa_port *dp)
|
||||
static void dsa_port_teardown(struct dsa_port *dp)
|
||||
{
|
||||
struct devlink_port *dlp = &dp->devlink_port;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct dsa_mac_addr *a, *tmp;
|
||||
|
||||
if (!dp->setup)
|
||||
return;
|
||||
|
||||
if (ds->ops->port_teardown)
|
||||
ds->ops->port_teardown(ds, dp->index);
|
||||
|
||||
devlink_port_type_clear(dlp);
|
||||
|
||||
switch (dp->type) {
|
||||
@ -581,6 +595,36 @@ static void dsa_port_devlink_teardown(struct dsa_port *dp)
|
||||
dp->devlink_port_setup = false;
|
||||
}
|
||||
|
||||
/* Destroy the current devlink port, and create a new one which has the UNUSED
|
||||
* flavour. At this point, any call to ds->ops->port_setup has been already
|
||||
* balanced out by a call to ds->ops->port_teardown, so we know that any
|
||||
* devlink port regions the driver had are now unregistered. We then call its
|
||||
* ds->ops->port_setup again, in order for the driver to re-create them on the
|
||||
* new devlink port.
|
||||
*/
|
||||
static int dsa_port_reinit_as_unused(struct dsa_port *dp)
|
||||
{
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
int err;
|
||||
|
||||
dsa_port_devlink_teardown(dp);
|
||||
dp->type = DSA_PORT_TYPE_UNUSED;
|
||||
err = dsa_port_devlink_setup(dp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ds->ops->port_setup) {
|
||||
/* On error, leave the devlink port registered,
|
||||
* dsa_switch_teardown will clean it up later.
|
||||
*/
|
||||
err = ds->ops->port_setup(ds, dp->index);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsa_devlink_info_get(struct devlink *dl,
|
||||
struct devlink_info_req *req,
|
||||
struct netlink_ext_ack *extack)
|
||||
@ -836,7 +880,7 @@ static int dsa_switch_setup(struct dsa_switch *ds)
|
||||
devlink_params_publish(ds->devlink);
|
||||
|
||||
if (!ds->slave_mii_bus && ds->ops->phy_read) {
|
||||
ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
|
||||
ds->slave_mii_bus = mdiobus_alloc();
|
||||
if (!ds->slave_mii_bus) {
|
||||
err = -ENOMEM;
|
||||
goto teardown;
|
||||
@ -846,13 +890,16 @@ static int dsa_switch_setup(struct dsa_switch *ds)
|
||||
|
||||
err = mdiobus_register(ds->slave_mii_bus);
|
||||
if (err < 0)
|
||||
goto teardown;
|
||||
goto free_slave_mii_bus;
|
||||
}
|
||||
|
||||
ds->setup = true;
|
||||
|
||||
return 0;
|
||||
|
||||
free_slave_mii_bus:
|
||||
if (ds->slave_mii_bus && ds->ops->phy_read)
|
||||
mdiobus_free(ds->slave_mii_bus);
|
||||
teardown:
|
||||
if (ds->ops->teardown)
|
||||
ds->ops->teardown(ds);
|
||||
@ -877,8 +924,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds)
|
||||
if (!ds->setup)
|
||||
return;
|
||||
|
||||
if (ds->slave_mii_bus && ds->ops->phy_read)
|
||||
if (ds->slave_mii_bus && ds->ops->phy_read) {
|
||||
mdiobus_unregister(ds->slave_mii_bus);
|
||||
mdiobus_free(ds->slave_mii_bus);
|
||||
ds->slave_mii_bus = NULL;
|
||||
}
|
||||
|
||||
dsa_switch_unregister_notifier(ds);
|
||||
|
||||
@ -938,12 +988,9 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
|
||||
list_for_each_entry(dp, &dst->ports, list) {
|
||||
err = dsa_port_setup(dp);
|
||||
if (err) {
|
||||
dsa_port_devlink_teardown(dp);
|
||||
dp->type = DSA_PORT_TYPE_UNUSED;
|
||||
err = dsa_port_devlink_setup(dp);
|
||||
err = dsa_port_reinit_as_unused(dp);
|
||||
if (err)
|
||||
goto teardown;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,6 +1095,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
|
||||
teardown_master:
|
||||
dsa_tree_teardown_master(dst);
|
||||
teardown_switches:
|
||||
dsa_tree_teardown_ports(dst);
|
||||
dsa_tree_teardown_switches(dst);
|
||||
teardown_cpu_ports:
|
||||
dsa_tree_teardown_cpu_ports(dst);
|
||||
@ -1562,3 +1610,53 @@ void dsa_unregister_switch(struct dsa_switch *ds)
|
||||
mutex_unlock(&dsa2_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dsa_unregister_switch);
|
||||
|
||||
/* If the DSA master chooses to unregister its net_device on .shutdown, DSA is
|
||||
* blocking that operation from completion, due to the dev_hold taken inside
|
||||
* netdev_upper_dev_link. Unlink the DSA slave interfaces from being uppers of
|
||||
* the DSA master, so that the system can reboot successfully.
|
||||
*/
|
||||
void dsa_switch_shutdown(struct dsa_switch *ds)
|
||||
{
|
||||
struct net_device *master, *slave_dev;
|
||||
LIST_HEAD(unregister_list);
|
||||
struct dsa_port *dp;
|
||||
|
||||
mutex_lock(&dsa2_mutex);
|
||||
rtnl_lock();
|
||||
|
||||
list_for_each_entry(dp, &ds->dst->ports, list) {
|
||||
if (dp->ds != ds)
|
||||
continue;
|
||||
|
||||
if (!dsa_port_is_user(dp))
|
||||
continue;
|
||||
|
||||
master = dp->cpu_dp->master;
|
||||
slave_dev = dp->slave;
|
||||
|
||||
netdev_upper_dev_unlink(master, slave_dev);
|
||||
/* Just unlinking ourselves as uppers of the master is not
|
||||
* sufficient. When the master net device unregisters, that will
|
||||
* also call dev_close, which we will catch as NETDEV_GOING_DOWN
|
||||
* and trigger a dev_close on our own devices (dsa_slave_close).
|
||||
* In turn, that will call dev_mc_unsync on the master's net
|
||||
* device. If the master is also a DSA switch port, this will
|
||||
* trigger dsa_slave_set_rx_mode which will call dev_mc_sync on
|
||||
* its own master. Lockdep will complain about the fact that
|
||||
* all cascaded masters have the same dsa_master_addr_list_lock_key,
|
||||
* which it normally would not do if the cascaded masters would
|
||||
* be in a proper upper/lower relationship, which we've just
|
||||
* destroyed.
|
||||
* To suppress the lockdep warnings, let's actually unregister
|
||||
* the DSA slave interfaces too, to avoid the nonsensical
|
||||
* multicast address list synchronization on shutdown.
|
||||
*/
|
||||
unregister_netdevice_queue(slave_dev, &unregister_list);
|
||||
}
|
||||
unregister_netdevice_many(&unregister_list);
|
||||
|
||||
rtnl_unlock();
|
||||
mutex_unlock(&dsa2_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dsa_switch_shutdown);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2019 NXP Semiconductors
|
||||
/* Copyright 2019 NXP
|
||||
*/
|
||||
#include <linux/dsa/ocelot.h>
|
||||
#include <soc/mscc/ocelot.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright 2020-2021 NXP Semiconductors
|
||||
/* Copyright 2020-2021 NXP
|
||||
*
|
||||
* An implementation of the software-defined tag_8021q.c tagger format, which
|
||||
* also preserves full functionality under a vlan_filtering bridge. It does
|
||||
|
@ -1982,6 +1982,8 @@ static int replace_nexthop_grp(struct net *net, struct nexthop *old,
|
||||
rcu_assign_pointer(old->nh_grp, newg);
|
||||
|
||||
if (newg->resilient) {
|
||||
/* Make sure concurrent readers are not using 'oldg' anymore. */
|
||||
synchronize_net();
|
||||
rcu_assign_pointer(oldg->res_table, tmp_table);
|
||||
rcu_assign_pointer(oldg->spare->res_table, tmp_table);
|
||||
}
|
||||
@ -3565,6 +3567,7 @@ static struct notifier_block nh_netdev_notifier = {
|
||||
};
|
||||
|
||||
static int nexthops_dump(struct net *net, struct notifier_block *nb,
|
||||
enum nexthop_event_type event_type,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct rb_root *root = &net->nexthop.rb_root;
|
||||
@ -3575,8 +3578,7 @@ static int nexthops_dump(struct net *net, struct notifier_block *nb,
|
||||
struct nexthop *nh;
|
||||
|
||||
nh = rb_entry(node, struct nexthop, rb_node);
|
||||
err = call_nexthop_notifier(nb, net, NEXTHOP_EVENT_REPLACE, nh,
|
||||
extack);
|
||||
err = call_nexthop_notifier(nb, net, event_type, nh, extack);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
@ -3590,7 +3592,7 @@ int register_nexthop_notifier(struct net *net, struct notifier_block *nb,
|
||||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
err = nexthops_dump(net, nb, extack);
|
||||
err = nexthops_dump(net, nb, NEXTHOP_EVENT_REPLACE, extack);
|
||||
if (err)
|
||||
goto unlock;
|
||||
err = blocking_notifier_chain_register(&net->nexthop.notifier_chain,
|
||||
@ -3603,8 +3605,17 @@ EXPORT_SYMBOL(register_nexthop_notifier);
|
||||
|
||||
int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&net->nexthop.notifier_chain,
|
||||
nb);
|
||||
int err;
|
||||
|
||||
rtnl_lock();
|
||||
err = blocking_notifier_chain_unregister(&net->nexthop.notifier_chain,
|
||||
nb);
|
||||
if (err)
|
||||
goto unlock;
|
||||
nexthops_dump(net, nb, NEXTHOP_EVENT_DEL, NULL);
|
||||
unlock:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(unregister_nexthop_notifier);
|
||||
|
||||
|
@ -1316,7 +1316,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
|
||||
goto alloc_skb;
|
||||
}
|
||||
|
||||
must_collapse = (info->size_goal - skb->len > 0) &&
|
||||
must_collapse = (info->size_goal > skb->len) &&
|
||||
(skb_shinfo(skb)->nr_frags < sysctl_max_skb_frags);
|
||||
if (must_collapse) {
|
||||
size_bias = skb->len;
|
||||
@ -1325,7 +1325,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
|
||||
}
|
||||
|
||||
alloc_skb:
|
||||
if (!must_collapse && !ssk->sk_tx_skb_cache &&
|
||||
if (!must_collapse &&
|
||||
!mptcp_alloc_tx_skb(sk, ssk, info->data_lock_held))
|
||||
return 0;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user